問題描述
過去幾個小時,我一直在網路上徘徊,想知道是否有辦法讓使用者透過選擇 WordPress 中的類別來構建自己的 RSS 源,然後可以透過電子郵件訂閱。似乎提出了兩個問題:
-
允許人們從類別中構建個性化的 Feed 。
-
啟用電子郵件訂閱。
任何關於如何最好地繼續下去的想法?
最佳解決辦法
這是一個很酷的主意。
我不認為 WordPress 中應該處理第 2 部分:電子郵件提供商有很多 RSS 。他們將會更好,而不是外掛 (或主題) 可能會更好。
但是我們可以建立 RSS 源。
第一步:設定一個課程來包裝所有的東西。
這裡有一些類常量和變數 – 稍後我們將使用它們。只是一個單身模式。
<?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;
}
}
第二步:向使用者個人資料頁面新增一個欄位 (並儲存)
您需要掛接到 show_user_profile 和 edit_user_profile 才能執行此操作。吐出一個廢紙,一個標籤和一個欄位。當使用者在管理區域中檢視其個人資料時,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);
}
}
}
第三步:提供飼料
由於這是一個非常自定義的 Feed,我們不想劫持像作者的 Feed 來完成這個操作 (雖然這是一個選項!) 。而是讓我們新增一個重寫:yoursite.com/user-feed/{{user_id}}將呈現個性化的使用者 Feed 。
要新增重寫,我們需要鉤入 init 並使用 add_rewrite_rule 。由於這使用自定義查詢變數來檢測何時使用個性化的使用者 Feed,因此我們還需要掛接到 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;
}
}
要實際呈現 Feed,我們將鉤入 template_redirect,查詢我們的自定義查詢 var(如果沒有找到它),並使用個性化版本劫持全域性 $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;
}
}
要實際渲染 Feed,我們依靠 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+。
次佳解決辦法
我使用常規 WordPress Category Feeds 和 MailChimp 來為我的電子郵件訂閱者提供只接收有興趣接收的類別的新帖子的選項。
在 MailChimp 中,您為每個 WordPress 類別建立一個組,然後在您的電子郵件訂閱表單上允許您的訂閱者選擇他們有興趣訂閱的組 (即,類別)(一組核取方塊可能最簡單) 。當他們訂閱時,他們的選擇將被傳遞,並將它們放在 MailChimp 上的這些組中。
然後在 MailChimp 上,您可以使用類別 Feed 為每個類別建立一個 RSS 廣告系列,並在廣告系列設定中指定只將新帖子傳送到訂閱者細分 (已選擇該類別對應的組) 。
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。