Benutzern erlauben, ihren eigenen Feed aus ausgewählten Kategorien zu erstellen?

7

Ich bin in den letzten Stunden im Internet herumgewandert und habe mich gefragt, ob es eine Möglichkeit gibt, Benutzern das Erstellen eines eigenen RSS-Feeds zu ermöglichen, indem sie Kategorien in WordPress auswählen, die dann per E-Mail abonniert werden können. Scheint zwei Probleme zu präsentieren:

  1. Ermöglichen, dass Personen einen personalisierten Feed aus Kategorien erstellen.
  2. E-Mail-Abonnement aktivieren.

Irgendwelche Gedanken darüber, wie man am besten vorgeht?

Christopher
quelle

Antworten:

7

Das ist eine wirklich coole Idee.

Ich denke nicht, dass Teil 2 in WordPress behandelt werden sollte: Es gibt viele RSS für E-Mail-Anbieter. Sie werden darin viel besser sein als ein Plugin (oder Thema) wahrscheinlich.

ABER wir können RSS-Feeds erstellen.

Schritt eins: Richten Sie eine Klasse ein, um alles zusammenzufassen.

Hier gibt es einige Klassenkonstanten und -variablen - wir werden sie später verwenden. Nur ein Singleton-Muster.

<?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;
    }
}

Schritt zwei: Fügen Sie den Benutzerprofilseiten ein Feld hinzu (und speichern Sie es).

Sie müssen sich einhaken show_user_profileund dies edit_user_profiletun. Spucken Sie eine Nonce, ein Etikett und das Feld aus. show_user_profileWird ausgelöst, wenn Benutzer ihr Profil im Administratorbereich anzeigen. edit_user_profileWird ausgelöst, wenn das Profil eines anderen Benutzers bearbeitet wird. So wird Ihr Administrator in die Kategorien eines Bearbeitungsbenutzers eingeordnet.

<?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>';
        }
    }
}

Damit werden auch unsere ersten beiden Hilfsmethoden vorgestellt:

  1. get_user_terms, ein einfacher Wraper get_user_metamit einem Aufruf an apply_filters- lassen Sie andere Dinge ändern, wenn sie wollen!
  2. get_termsein Wrapper get_termsmit einem Anruf an apply_filters.

Beides sind nur Annehmlichkeiten. Sie bieten auch Möglichkeiten für andere Plugins / Themes, Dinge einzubinden und zu ändern.

<?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);
}

Um die Felder zu speichern, klicken Sie auf personal_options_update(wird ausgelöst, wenn der Benutzer sein eigenes Profil speichert) und edit_user_profile_update(wird ausgelöst, wenn das Profil eines anderen Benutzers gespeichert wird).

<?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);
        }
    }
}

Schritt drei: Geben Sie einen Feed ein

Da es sich um einen benutzerdefinierten Feed handelt, möchten wir keine Autoren-Feeds entführen, um dies zu erreichen (obwohl dies eine Option ist!). Fügen wir stattdessen ein Umschreiben hinzu: yoursite.com/user-feed/{{user_id}}Rendert den personalisierten Benutzer-Feed.

Um das Umschreiben hinzuzufügen, müssen wir uns einhaken initund verwenden add_rewrite_rule. Da dies eine benutzerdefinierte Abfragevariable verwendet, um zu erkennen, wann wir uns in einem personalisierten Benutzer-Feed befinden, müssen wir uns auch in query_varsunsere benutzerdefinierte Variable einbinden, damit WordPress sie nicht ignoriert.

<?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;
    }
}

Um den Feed tatsächlich zu rendern, werden wir uns anschließen template_redirect, nach unserer benutzerdefinierten Abfragevariablen suchen (Kaution, wenn wir sie nicht finden) und die globale $wp_querymit einer personalisierten Version entführen .

Ich habe mich auch daran gewöhnt wp_title_rss, den RSS-Titel zu ändern, was etwas seltsam war: Er hat die erste Kategorie erfasst und den Feed-Titel so angezeigt, als würde er eine einzelne Kategorie betrachten.

<?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;
    }
}

Um den Feed tatsächlich zu rendern, verlassen wir uns darauf wp-includes/feed-rss2.php. Sie könnten dies durch etwas Benutzerdefinierteres ersetzen, aber warum nicht faul sein?

Hier gibt es auch eine dritte Hilfsmethode : get_user_query. Dieselbe Idee wie die oben genannten Helfer - abstrahieren Sie einige wiederverwendbare Funktionen und stellen Sie Hooks bereit.

<?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);
}

Hier ist alles oben als Plugin . Das Plugin (und anschließend diese Antwort) benötigt aufgrund der Verwendung anonymer Funktionen PHP 5.3+.

chrisguitarguy
quelle
1
Sie erhalten eine +1 für die Mühe!
Adam
3

Ich verwende dazu die regulären WordPress-Kategorie-Feeds und MailChimp , um meinen E-Mail-Abonnenten die Möglichkeit zu geben, neue Beiträge nur für Kategorien zu erhalten, die sie erhalten möchten .

In MailChimp erstellen Sie eine Gruppe für jede WordPress-Kategorie und erlauben Ihren Abonnenten dann in Ihrem E-Mail-Anmeldeformular, die Gruppen (dh Kategorien) auszuwählen, die sie abonnieren möchten (eine Reihe von Kontrollkästchen ist wahrscheinlich am einfachsten). Wenn sie sich anmelden, wird ihre Auswahl weitergegeben und sie werden auf MailChimp in diese Gruppen eingeteilt.

Anschließend erstellen Sie in MailChimp mithilfe des Kategorie-Feeds eine RSS-Kampagne für jede Kategorie und geben in den Kampagneneinstellungen an, dass nur neue Beiträge an ein Segment Ihrer Abonnenten gesendet werden sollen (das Segment, das die dieser Kategorie entsprechende Gruppe ausgewählt hat).

Raam Dev
quelle
1

Am einfachsten wäre es, eine Reihe von zwei sehr kurzen (Mu-) Plugins hinzuzufügen. Dies fügt auch Routen für page/2usw.: Hinzu.

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'
    );
}
Kaiser
quelle
0

WordPress liefert bereits RSS-Feeds für jede Kategorie. Dies ist der Codex-Artikel, der erklärt, wie sie strukturiert sind:

http://codex.wordpress.org/WordPress_Feeds#Categories_and_Tags

Damit das E-Mail-Abonnement funktioniert, habe ich Feedburner normalerweise mit aktiviertem E-Mail-Abonnement eingerichtet (nachdem Sie einen Feed angefordert haben, gehen Sie zu Veröffentlichen> E-Mail-Abonnements). Dazu müssten Sie Ihre Kategorie-Feeds in Feedburner einrichten und diese Links an geeigneten Stellen zu Ihrer Site hinzufügen. Wenn Sie mit einer Menge Kategorien zu tun haben, ist das möglicherweise ein ziemlicher Arbeitsaufwand. Hoffentlich haben andere Leute hier Vorschläge.

Viel Glück!

Michelle
quelle
Danke Michelle. So viel kenne ich leider. Was ich herausfinden möchte, ist eine Möglichkeit, Kategorien in einer ausgewählten Form oder so aufzulisten und dann ihren benutzerdefinierten Feed im Handumdrehen der Kategorien zu erstellen, die sie abonnieren möchten, anstatt sie zu zwingen, eine Reihe von Kategorie-Feeds unabhängig voneinander zu abonnieren . Entschuldigung, wenn das nicht klar war.
Christopher