Cho phép người dùng tạo nguồn cấp dữ liệu của riêng họ từ các danh mục đã chọn?


7

Tôi đã lang thang trên web trong vài giờ qua để tự hỏi liệu có cách nào cho phép người dùng xây dựng nguồn cấp RSS của riêng họ bằng cách chọn các danh mục trong WordPress, sau đó có thể được đăng ký qua email. Có vẻ như trình bày hai vấn đề:

  1. Cho phép mọi người xây dựng một nguồn cấp dữ liệu cá nhân từ các danh mục.
  2. Kích hoạt đăng ký email.

Bất kỳ suy nghĩ về cách tốt nhất để tiến hành với một trong hai?

Câu trả lời:


7

Đó là một ý tưởng tuyệt vời.

Tôi không nghĩ phần 2 nên được xử lý trong WordPress: có rất nhiều RSS cho các nhà cung cấp email. Họ sẽ trở nên tốt hơn ở đó hơn là một plugin (hoặc chủ đề) có khả năng.

NHƯNG chúng ta có thể tạo nguồn cấp RSS.

Bước một: thiết lập một lớp để bọc mọi thứ.

Có một vài hằng số lớp và biến ở đây - chúng ta sẽ sử dụng chúng sau. Chỉ là một mẫu đơn.

<?php
class Per_User_Feeds
{
    // Where we'll store the user cats
    const META_KEY = '_per_user_feeds_cats';

    // Nonce for the form fields
    const NONCE = '_user_user_feeds_nonce';

    // Taxonomy to use
    const TAX = 'category';

    // The query variable for the rewrite
    const Q_VAR = 'puf_feed';

    // container for the instance of this class
    private static $ins = null;

    // container for the terms allowed for this plugin
    private static $terms = null;

    public static function init()
    {
        add_action('plugins_loaded', array(__CLASS__, 'instance'));
    }

    public static function instance()
    {
        is_null(self::$ins) && self::$ins = new self;
        return self::$ins;
    }
}

Bước hai: thêm một trường vào các trang hồ sơ người dùng (và lưu nó)

Bạn sẽ cần phải nối vào show_user_profileedit_user_profileđể làm điều này. Nhổ ra một nonce, nhãn và trường. show_user_profilecháy khi người dùng xem hồ sơ của họ trong khu vực quản trị. edit_user_profilekích hoạt khi họ chỉnh sửa hồ sơ của người khác - đây là cách người dùng quản trị viên của bạn sẽ đi vào danh mục người dùng chỉnh sửa.

<?php
class Per_User_Feeds
{
    // snip snip

    protected function __construct()
    {
        add_action('show_user_profile', array($this, 'field'));
        add_action('edit_user_profile', array($this, 'field'));
    }

    public function field($user)
    {
        wp_nonce_field(self::NONCE . $user->ID, self::NONCE, false);

        echo '<h4>', esc_html__('Feed Categories', 'per-user-feed'), '</h4>';

        if($terms = self::get_terms())
        {
            $val = self::get_user_terms($user->ID);
            printf('<select name="%1$s[]" id="%1$s" multiple="multiple">', esc_attr(self::META_KEY));
            echo '<option value="">', esc_html__('None', 'per-user-feed'), '</option>';
            foreach($terms as $t)
            {
                printf(
                    '<option value="%1$s" %3$s>%2$s</option>',
                    esc_attr($t->term_id),
                    esc_html($t->name),
                    in_array($t->term_id, $val) ? 'selected="selected"' : ''
                );
            }
            echo '</select>';
        }
    }
}

Điều đó cũng giới thiệu hai phương thức trợ giúp đầu tiên của chúng tôi:

  1. get_user_terms, một trình bao bọc đơn giản xung quanh get_user_metavới một lời kêu gọi apply_filters- hãy để người khác sửa đổi mọi thứ nếu họ muốn!
  2. get_termsmột bọc xung quanh get_termsvới một cuộc gọi đến apply_filters.

Cả hai điều này chỉ là những điều tiện lợi. Họ cũng cung cấp các cách để các plugin / chủ đề khác kết nối và sửa đổi mọi thứ.

<?php
/**
 * Get the categories available for use with this plugin.
 *
 * @uses    get_terms
 * @uses    apply_filters
 * @return  array The categories for use
 */
public static function get_terms()
{
    if(is_null(self::$terms))
        self::$terms = get_terms(self::TAX, array('hide_empty' => false));

    return apply_filters('per_user_feeds_terms', self::$terms);
}

/**
 * Get the feed terms for a given user.
 *
 * @param   int $user_id The user for which to fetch terms
 * @uses    get_user_meta
 * @uses    apply_filters
 * @return  mixed The array of allowed term IDs or an empty string
 */
public static function get_user_terms($user_id)
{
    return apply_filters('per_user_feeds_user_terms',
        get_user_meta($user_id, self::META_KEY, true), $user_id);
}

Để lưu các trường, hãy nối vào personal_options_update(kích hoạt khi người dùng lưu hồ sơ của chính họ) và edit_user_profile_update(kích hoạt khi lưu hồ sơ của người dùng khác).

<?php
class Per_User_Feeds
{
    // snip snip

    protected function __construct()
    {
        add_action('show_user_profile', array($this, 'field'));
        add_action('edit_user_profile', array($this, 'field'));
        add_action('personal_options_update', array($this, 'save'));
        add_action('edit_user_profile_update', array($this, 'save'));
    }

    // snip snip

    public function save($user_id)
    {
        if(
            !isset($_POST[self::NONCE]) ||
            !wp_verify_nonce($_POST[self::NONCE], self::NONCE . $user_id)
        ) return;

        if(!current_user_can('edit_user', $user_id))
            return;

        if(!empty($_POST[self::META_KEY]))
        {
            $allowed = array_map(function($t) {
                return $t->term_id;
            }, self::get_terms());

            // PHP > 5.3: Make sure the items are in our allowed terms.
            $res = array_filter(
                (array)$_POST[self::META_KEY],
                function($i) use ($allowed) {
                    return in_array($i, $allowed);
                }
            );

            update_user_meta($user_id, self::META_KEY, array_map('absint', $res));
        }
        else
        {
            delete_user_meta($user_id, self::META_KEY);
        }
    }
}

Bước ba: cung cấp một nguồn cấp dữ liệu

Vì đây là rất nhiều nguồn cấp dữ liệu tùy chỉnh, chúng tôi không muốn chiếm quyền điều gì đó như nguồn cấp dữ liệu của tác giả để thực hiện việc này (mặc dù đó là một tùy chọn!). Thay vào đó, hãy thêm viết lại: yoursite.com/user-feed/{{user_id}}sẽ hiển thị nguồn cấp dữ liệu người dùng được cá nhân hóa.

Để thêm phần viết lại, chúng ta cần nối vào initvà sử dụng add_rewrite_rule. Vì điều này sử dụng biến truy vấn tùy chỉnh để phát hiện khi chúng tôi sử dụng nguồn cấp dữ liệu người dùng được cá nhân hóa, chúng tôi cũng cần nối vào query_varsvà biến tùy chỉnh của chúng tôi để WordPress không bỏ qua nó.

<?php
class Per_User_Feeds
{
    // snip snip

    protected function __construct()
    {
        add_action('show_user_profile', array($this, 'field'));
        add_action('edit_user_profile', array($this, 'field'));
        add_action('personal_options_update', array($this, 'save'));
        add_action('edit_user_profile_update', array($this, 'save'));
        add_action('init', array($this, 'rewrite'));
        add_filter('query_vars', array($this, 'query_var'));
    }

    // snip snip

    public function rewrite()
    {
        add_rewrite_rule(
            '^user-feed/(\d+)/?$',
            'index.php?' . self::Q_VAR . '=$matches[1]',
            'top'
        );
    }

    public function query_var($v)
    {
        $v[] = self::Q_VAR;
        return $v;
    }
}

Để thực sự kết xuất nguồn cấp dữ liệu, chúng tôi sẽ kết nối template_redirect, tìm kiếm var truy vấn tùy chỉnh của chúng tôi (bảo đảm nếu chúng tôi không tìm thấy nó) và chiếm quyền điều khiển toàn cầu $wp_querybằng phiên bản được cá nhân hóa.

Tôi cũng nối vào wp_title_rssđể sửa đổi tiêu đề RSS, điều này hơi lạ: nó lấy danh mục đầu tiên và hiển thị tiêu đề nguồn cấp dữ liệu như thể nhìn vào một danh mục duy nhất.

<?php
class Per_User_Feeds
{
    // snip snip

    protected function __construct()
    {
        add_action('show_user_profile', array($this, 'field'));
        add_action('edit_user_profile', array($this, 'field'));
        add_action('personal_options_update', array($this, 'save'));
        add_action('edit_user_profile_update', array($this, 'save'));
        add_action('init', array($this, 'rewrite'));
        add_filter('query_vars', array($this, 'query_var'));
        add_action('template_redirect', array($this, 'catch_feed'));
    }

    // snip snip

    public function catch_feed()
    {
        $user_id = get_query_var(self::Q_VAR);

        if(!$user_id)
            return;

        if($q = self::get_user_query($user_id))
        {
            global $wp_query;
            $wp_query = $q;

            // kind of lame: anon function on a filter...
            add_filter('wp_title_rss', function($title) use ($user_id) {
                $title = ' - ' . __('User Feed', 'per-user-feed');

                if($user = get_user_by('id', $user_id))
                    $title .= ': ' . $user->display_name;

                return $title;
            });
        }

        // maybe want to handle the "else" here?

        // see do_feed_rss2
        load_template( ABSPATH . WPINC . '/feed-rss2.php' );
        exit;
    }
}

Để thực sự kết xuất nguồn cấp dữ liệu, chúng tôi dựa vào wp-includes/feed-rss2.php. Bạn có thể thay thế điều này bằng một cái gì đó tùy chỉnh hơn, nhưng tại sao không lười biếng?

Cũng có một phương pháp trợ giúp thứ ba ở đây : get_user_query. Ý tưởng tương tự như những người trợ giúp ở trên - trừu tượng hóa một số chức năng có thể tái sử dụng và cung cấp các hook.

<?php
/**
 * Get a WP_Query object for a given user.
 *
 * @acces   public
 * @uses    WP_Query
 * @return  object WP_Query
 */
public static function get_user_query($user_id)
{
    $terms = self::get_user_terms($user_id);

    if(!$terms)
        return apply_filters('per_user_feeds_query_args', false, $terms, $user_id);

    $args = apply_filters('per_user_feeds_query_args', array(
        'tax_query' => array(
            array(
                'taxonomy'  => self::TAX,
                'terms'     => $terms,
                'field'     => 'id',
                'operator'  => 'IN',
            ),
        ),
    ), $terms, $user_id);

    return new WP_Query($args);
}

Đây là tất cả các bên trên như là một plugin . Plugin (và sau đó, câu trả lời này) yêu cầu PHP 5.3+ do sử dụng các hàm ẩn danh.


1
Bạn nhận được +1 cho nỗ lực!
Adam

3

Tôi thực hiện việc này bằng cách sử dụng Nguồn cấp dữ liệu danh mục WordPressMailChimp thông thường để cung cấp cho người đăng ký email của tôi tùy chọn chỉ nhận bài đăng mới cho các danh mục họ muốn nhận.

Trong MailChimp, bạn tạo Nhóm cho từng danh mục WordPress và sau đó trên biểu mẫu đăng ký email của bạn, bạn cho phép người đăng ký của mình chọn các nhóm (tức là danh mục) mà họ quan tâm để đăng ký (một bộ hộp kiểm có thể dễ nhất). Khi họ đăng ký, các lựa chọn của họ sẽ được chuyển qua và họ sẽ được đưa vào các nhóm đó trên MailChimp.

Sau đó, trên MailChimp bạn tạo Chiến dịch RSS cho từng danh mục bằng Nguồn cấp dữ liệu và chỉ định trong cài đặt chiến dịch để chỉ gửi bài đăng mới đến một phân khúc người đăng ký của bạn (phân khúc đã chọn nhóm tương ứng với danh mục đó).


1

Đơn giản nhất là thêm một loạt hai plugin (mu-) rất ngắn. Điều này cũng thêm các tuyến đường cho page/2, v.v.:

http://example.com/u/%author%

<?php
/** Plugin Name: (WPSE) #46074 Add /u/%author% routes */

register_activation_hook(   __FILE__, function() { flush_rewrite_rules(); } );
register_deactivation_hook( __FILE__, function() { flush_rewrite_rules(); } );

add_action( 'init', function()
{
    // Adds `/u/{$author_name}` routes
    add_rewrite_rule(
        'u/([^/]+)/?',
        'index.php?author_name=$matches[1]',
        'top'
    );
    add_rewrite_rule(
        'u/([^/]+)/page/?([0-9]{1,})/?',
        'index.php?author_name=$matches[1]&paged=$matches[2]',
        'top'
    );
}

http://example.com/p/%postname%

<?php
/** Plugin Name: (WPSE) #46074 Add /u/%author% routes */

register_activation_hook(   __FILE__, function() { flush_rewrite_rules(); } );
register_deactivation_hook( __FILE__, function() { flush_rewrite_rules(); } );

add_action( 'init', function()
{
    // Adds `/p/{$postname}` routes
    add_rewrite_rule(
        'p/([^/]+)/?',
        'index.php?p=$matches[1]',
        'top'
    );
    add_rewrite_rule(
        'p/([^/]+)/page/?([0-9]{1,})/?',
        'index.php?p=$matches[1]&paged=$matches[2]',
        'top'
    );
}

0

WordPress đã cung cấp nguồn cấp dữ liệu RSS cho từng danh mục, đây là bài viết về codex giải thích cách chúng được cấu trúc:

http://codex.wordpress.org/WordPress_Feed#C chuyên_and_Tags

Để làm cho đăng ký email hoạt động, tôi thường thiết lập Feedburner với đăng ký email được bật (sau khi yêu cầu một nguồn cấp dữ liệu, hãy đi tới Công khai hóa> Đăng ký email). Điều đó sẽ yêu cầu bạn lấy nguồn cấp dữ liệu danh mục của bạn và thiết lập từng nguồn cấp dữ liệu trong Feedburner, sau đó thêm các liên kết đó vào trang web của bạn ở những nơi thích hợp. Nếu bạn đang xử lý một tấn các danh mục có thể khá nhiều công việc. Hy vọng những người khác ở đây sẽ có đề xuất.

May mắn nhất!


Cảm ơn Michelle. Thật không may, tôi rất quen thuộc. Những gì tôi đang cố gắng tìm ra là một cách liệt kê các danh mục trong một hình thức chọn lọc hoặc một cái gì đó và sau đó xây dựng nguồn cấp dữ liệu tùy chỉnh của họ theo cách nhanh chóng của các danh mục mà họ muốn đăng ký thay vì buộc họ phải đăng ký một loạt các nguồn cấp dữ liệu danh mục một cách độc lập . Xin lỗi nếu điều đó không rõ ràng.
Christopher
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.