这是个很酷的主意。
我认为第2部分不应该在WordPress内部处理:有很多RSS到电子邮件提供商。他们将比插件(或主题)在这方面做得更好。
但我们可以创建RSS提要。
Step one: set up a class to wrap everything up.
这里有几个类常量和变量——我们稍后将使用它们。只是一个单件模式。
<?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;
}
}
Step two: add a field to the user profile pages (and save it)
你需要加入
show_user_profile
和
edit_user_profile
这样做。弹出一个nonce、一个标签和字段。
show_user_profile
当用户在管理区域查看其配置文件时激发。
edit_user_profile
当他们编辑其他人的配置文件时激发--这是您的管理员用户在编辑用户类别中的方式。
<?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>\';
}
}
}
这还介绍了我们的前两个助手方法:
get_user_terms
, 一个简单的包裹器get_user_meta
打电话给apply_filters
-- 如果别人愿意,就让他们修改吧get_terms
包裹物get_terms
打电话给apply_filters
.
这两个都是方便的事情。它们还为其他插件/主题提供了连接和修改内容的方法。
<?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);
}
要保存字段,请连接到
personal_options_update
(当用户保存自己的配置文件时激发)和
edit_user_profile_update
(保存其他用户的配置文件时激发)。
<?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);
}
}
}
Step three: provide a feed
由于这在很大程度上是一个自定义提要,我们不想劫持像author提要这样的东西来完成这项工作(尽管这是一种选择!)。相反,让我们添加一个重写:
yoursite.com/user-feed/{{user_id}}
将呈现个性化用户提要。
要添加我们需要连接到的重写init
和使用add_rewrite_rule
. 由于这使用了一个自定义查询变量来检测何时使用个性化的用户提要,因此我们还需要连接到query_vars
以及我们的自定义变量,以便WordPress不会忽略它。
<?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;
}
}
要实际渲染提要,我们将
template_redirect
, 查找我们的自定义查询var(如果找不到,则进行bailing),并劫持全局
$wp_query
具有个性化版本。
我还迷上了wp_title_rss
修改RSS标题,这有点奇怪:它抓取了第一个类别,并显示提要标题,就像查看单个类别一样。
<?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;
}
}
实际渲染我们所依赖的提要
wp-includes/feed-rss2.php
. 你可以用一些更习惯的东西来代替它,但为什么不懒惰呢?
这里还有第三个助手方法:get_user_query
. 与上述助手的想法相同——抽象出一些可重用的功能并提供挂钩。
<?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);
}
以上都是
as a plugin. 由于使用匿名函数,该插件(以及随后的回答)需要PHP 5.3+。