Đó 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_profile
và edit_user_profile
để làm điều này. Nhổ ra một nonce, nhãn và trường. show_user_profile
cháy khi người dùng xem hồ sơ của họ trong khu vực quản trị. edit_user_profile
kí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:
get_user_terms
, một trình bao bọc đơn giản xung quanh get_user_meta
vớ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!
get_terms
một bọc xung quanh get_terms
vớ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 init
và 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_vars
và 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_query
bằ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.