wpGrafie

<?php /* Präsentiert auch coole Codeschnipsel */ ?>

Feed abonnieren

WordPress Page Template für einen Google+ Feed

WordPress Page Template für einen Google+ Feed

Google+ ist im Kommen, auch gerade wegen den neuen Unternehmensseiten, welche unter anderem als Blog genutzt werden können. Doch einen RSS Feed sucht man vergeblich.

Google+ Your Business

Unternehmensseite: Google+ Your Business

Für mein ProjektWordPress Trac Activity wolte ich für die nicht Google+ Nutzer einen Feed anbieten. Google selbst bietet aber keinen Feed für den Google+ Stream an.

Aus diesem Grund habe ich ein Page Template für WordPress entwickelt, welches die Möglichkeit bietet, einen Feed für einen Google+ Stream zu erstellen.
Ein Beispiel, der Feed für Trac Activity, ist unter wphelper.de/wp-trac-activity/ zu finden.

Das Page Template

Folgend der etwas größere Schnipsel mit anschließender Erklärung.

<?php
/**
* Template Name: Google+ Feed
*/


/**
* A WordPress page template for a Google+ feed.
*
* @author Dominik Schilling
* @license GPLv2
* @link http://wpgrafie.de/567/
*
* @version 0.2
*/
class Google_Plus_Feed {
/**
* Google+ API Key.
* See https://code.google.com/apis/console/
*
* @since 0.1
*
* @var string
*/
private $api_key = '';

/**
* Google+ User ID.
*
* @since 0.1
*
* @var string
*/
private $user_id = '';

/**
* Custom settings.
* See $this->set_settings()
*
* @since 0.1
*
* @var array
*/
private $settings = array();

/**
* Don't change the lines after these
* if you don't know what you do.
*/

/**
* Google+ activities.
*
* @since 0.1
*
* @var mixed
*/
private $activities;

/**
* Current queried object.
*
* @since 0.1
*
* @var object
*/
private $curr_obj;

/**
* Construct.
*
* @since 0.1
*
* @return void
*/
function __construct() {
if( empty( $this->curr_obj ) )
$this->curr_obj = get_queried_object();

if( ! $this->get_api_key() || ! $this->get_user_id() )
wp_die( 'Not configured!' );

$this->set_settings();

$this->activities = $this->build_activities();

if ( empty( $this->activities ) )
wp_die( 'Please load again.' );

$this->feed_output();
}

/**
* Get the API key from
* post custom field (gplusfeed_api_key)
* or
* $this->api_key
*
* @since 0.1
*
* @return string|bool Key on success, false if key is missing.
*/
function get_api_key() {
$api_key = get_post_meta( $this->curr_obj->ID, 'gplusfeed_api_key', true );

if ( ! empty( $api_key ) )
return $api_key;
else if( ! empty( $this->api_key ) )
return $this->api_key;
else
return false;
}

/**
* Get the user id from
* post custom field (gplus_feed_user_id)
* or
* $this->user_id
*
* @since 0.1
*
* @return string|bool Key on success, false if key is missing.
*/
function get_user_id() {
$user_id = get_post_meta( $this->curr_obj->ID, 'gplus_feed_user_id', true );

if ( ! empty( $user_id ) )
return $user_id;
else if( ! empty( $this->user_id ) )
return $this->user_id;
else
return false;
}

/**
* Set custom feed settings.
*
* - limit: How many activities should be displayed in feed
* - cache_time: How long the feed should be cached
* - language: The language of the feed
* - update_period: See http://web.resource.org/rss/1.0/modules/syndication/
* - update_frequency: See http://web.resource.org/rss/1.0/modules/syndication/
*
* @since 0.1
*
* @return array Settings saved in an array.
*/
function set_settings() {
$this->settings = wp_parse_args(
array(
'limit' => 10,
'cache_time' => 300,
'language' => 'de',
'update_period' => 'hourly',
'update_frequency' => 1
),
$this->settings
);
}

/**
* Get the Google+ API link.
* See https://developers.google.com/+/api/latest/activities/list
*
* @since 0.1
*
* @return string URL of the Google+ API.
*/
function get_api_link() {
$api_link = add_query_arg(
array(
'alt' => 'json',
'maxResults' => $this->settings['limit'],
'pp' => 1,
'key' => $this->get_api_key()
),
sprintf( 'https://www.googleapis.com/plus/v1/people/%s/activities/public', $this->get_user_id() )
);

return esc_url_raw( $api_link );
}

/**
* Build the activity stream and save it in a transient.
*
* @since 0.1
*
* @return string|bool Activities in XML format or false on error.
*/
function build_activities() {
$dev = true;
if ( false !== ( $activities = get_transient( $this->get_cache_key() ) ) && ! $dev )
return $activities;

$activities = $this->get_activities();

if ( is_wp_error( $activities ) )
return false;

$activities = $this->render_activities( $activities );

if ( empty( $activities ) )
return false;

// Cache activities
set_transient( $this->get_cache_key(), $activities, $this->settings['cache_time'] );

return $activities;
}

/**
* Build an individual cache key.
* Based on settings, user id and API key.
*
* @since 0.1
*
* @return string The cache key.
*/
function get_cache_key() {
return 'gplus_feed_' . md5(
implode( '|', $this->settings )
. $this->get_user_id()
. $this->get_api_key()
);
}

/**
* Get the activities from Google+ API.
*
* @since 0.1
*
* @return array|WP_Error API result in an array or WP_Error on API/HTTP error.
*/
function get_activities() {
$result = wp_remote_retrieve_body(
wp_remote_get(
$this->get_api_link()
)
);

if ( ! empty( $result ) ) {
$result = (array) json_decode( $result );

if ( empty ( $results->error ) )
return $result;
else
return new WP_Error( 'api_error', 'API ERROR', $results->error );
} else {
return new WP_Error( 'http_error', 'HTTP ERROR');
}
}

/**
* Render the activities and return them in XML format.
*
* @since 0.1
*
* @param array $activities
* @return array Rendered activity items for feed.
*/
function render_activities( $activities ) {
$feed = array();

foreach( $activities['items'] as $item => $data ) {
if ( ! preg_match('/^<bb[^>]*>(.*?)</b>/i', $data->object->content, $matches ) ) {
$title = $data->title;
$content = $data->object->content;
} else {
$title = strip_tags( $matches[1] );
$content = str_replace( $matches[0] . '<br /><br />', '', $data->object->content );
}

if ( ! empty( $data->object->attachments ) )
$content .= $this->_render_activity_attachments( $data->object->attachments );

$feed[$item] = "
<item>
<title>{$title}</title>
<link>{$data->url}</link>
<pubDate>" . mysql2date( 'D, d M Y H:i:s +0000', $data->published, false ) . "</pubDate>
<dc:creator>{$data->actor->displayName}</dc:creator>
<guid isPermaLink="false">{$data->url}</guid>

<description><![CDATA[" . wp_trim_words( $content, 20 ) . "]]></description>
<content:encoded><![CDATA[{$content}]]></content:encoded>

<slash:comments>{$data->object->replies->totalItems}</slash:comments>
</item>
";
}

return $feed;
}

/**
* Handle activity attachments, like video, photo and links (articles).
*
* @since 0.2
*
* @param array $attachments
* @return string Attachments in HTML format.
*/
function _render_activity_attachments( $attachments ) {
$articles = $photos = $videos = array();

foreach ( $attachments as $attachment => $meta ) {
switch ( $meta->objectType ) {
case 'article' :
$host = @parse_url( $meta->url, PHP_URL_HOST );
$articles[] = sprintf(
'%s<a href="%s" title="%s">%s</a>',
empty( $host ) ? '' : $host . ' – ',
esc_url( $meta->url ),
empty( $meta->content ) ? '' : esc_attr( $meta->content ),
empty( $meta->displayName ) ? '' : $meta->displayName
);
break;
case 'photo' :
$photos[] = sprintf(
'%s<img src="%s" height="%s" width="%s" alt="%s" title="%s" style="margin:5px;max-width:250px;height:auto" />%s',
empty( $meta->fullImage->url ) ? '' : '<a href="' . esc_url( $meta->fullImage->url ) . '">',
esc_url( $meta->image->url ),
empty( $meta->image->height ) ? '' : esc_attr( $meta->image->height ),
empty( $meta->image->width ) ? '' : esc_attr( $meta->image->width ),
empty( $meta->displayName ) ? '' : $meta->displayName,
empty( $meta->displayName ) ? '' : $meta->displayName,
empty( $meta->fullImage->url ) ? '' : '</a>'
);
break;
case 'video' :
$videos[] = sprintf(
'<a href="%s"><img src="%s" height="%s" width="%s" alt="%s" title="%s" style="margin:5px;max-width:250px;height:auto" /></a>',
esc_url( $meta->url ),
esc_url( $meta->image->url ),
empty( $meta->image->height ) ? '' : esc_attr( $meta->image->height ),
empty( $meta->image->width ) ? '' : esc_attr( $meta->image->width ),
empty( $meta->displayName ) ? '' : $meta->displayName,
empty( $meta->displayName ) ? '' : $meta->displayName
);
break;
}
}

$content = '';
$_html = '<div style="display:table-row"><div style="display:table-cell;vertical-align:top;padding:0 10px 0 0"><b>%s:</b></div>';
if ( ! empty( $articles ) ) {
$articles = implode( '<br />', $articles );
$content .= sprintf(
$_html,
__( 'Links' )
);
$content .= sprintf(
'<div style="display:table-cell">%s</div></div>',
$articles
);
}

if ( ! empty( $photos ) ) {
$photos = implode( '', $photos );
$content .= sprintf(
$_html,
__( 'Images' )
);
$content .= sprintf(
'<div style="display:table-cell">%s</div></div>',
$photos
);
}

if ( ! empty( $videos ) ) {
$videos = implode( '', $videos );
$content .= sprintf(
$_html,
__( 'Video' )
);
$content .= sprintf(
'<div style="display:table-cell">%s</div></div>',
$videos
);
}

if ( ! empty( $content ) )
$content = sprintf(
'<br /><br /><h4>%s</h4><div style="display:table">%s</div>',
__( 'Images and Attachments' ),
$content
);

return $content;
}

/**
* Build the feed output.
*
* @since 0.1
*
* @return void
*/
function feed_output() {
$this->get_rss_header();
$this->get_rss_content();
$this->get_rss_footer();
}

/**
* Retrieve information about the feed.
*
* @since 0.1
*
* @param string $show Feed info to retrieve.
* @param bool $echo Return or print the info. Default: true.
* @return string Feed info.
*/
function get_feed_info( $show, $echo = true ) {
switch ( $show ) {
case 'title' :
$output = apply_filters( 'the_title_rss', $this->curr_obj->post_title ) ;
break;
case 'self' :
$host = @parse_url( home_url() );
$host = $host['host'];
$output = esc_url(
( is_ssl() ? 'https' : 'http' ) . '://'
. $host
. stripslashes( $_SERVER['REQUEST_URI'] )
);
break;
case 'link' :
$output = esc_url( sprintf( 'https://plus.google.com/%d/', $this->get_user_id() ) );
break;
case 'desc' :
$output = apply_filters( 'the_title_rss', $this->curr_obj->post_content );
break;
case 'time' :
$timeout = get_option( '_transient_timeout_' . $this->get_cache_key() );
if ( $timeout === false )
$time = time();
else
$time = $timeout - $this->settings['cache_time'];
$output = date( 'D, d M Y H:i:s +0000', $time );
break;
case 'language' :
$output = $this->settings['language'];
break;
case 'update_period' :
$output = $this->settings['update_period'];
break;
case 'update_frequency' :
$output = $this->settings['update_frequency'];
break;
}

if( ! $echo )
return $output;

echo $output;
}

/**
* Print the feed header.
*
* @since 0.1
*
* @return void
*/
function get_rss_header() {
header( 'Content-Type: text/xml; charset=UTF-8', true );
echo '<?xml version="1.0" encoding="UTF-8"?'.'>';
?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
<channel>
<title><?php $this->get_feed_info( 'title' ); ?></title>
<atom:link href="<?php $this->get_feed_info( 'self' ); ?>" rel="self" type="application/rss+xml" />
<link><?php $this->get_feed_info( 'link' ); ?></link>
<description><?php $this->get_feed_info( 'desc' ); ?></description>
<lastBuildDate><?php $this->get_feed_info( 'time' ); ?></lastBuildDate>
<language><?php $this->get_feed_info( 'language' ); ?></language>
<sy:updatePeriod><?php $this->get_feed_info( 'update_period' ); ?></sy:updatePeriod>
<sy:updateFrequency><?php $this->get_feed_info( 'update_frequency' ); ?></sy:updateFrequency>
<?php
}

/**
* Print the feed content/activities.
*
* @since 0.1
*
* @return void
*/
function get_rss_content() {
foreach( $this->activities as $item )
echo $item;
}

/**
* Print the feed footer.
*
* @since 0.1
*
* @return void
*/
function get_rss_footer() {
?>
</channel>
</rss>
<?php
}
}

// Init
$feed = new Google_Plus_Feed();

Das obige Page Template sollte mit jedem Theme kompatibel sein und muss ins das Themeverzeichnis des aktuellen Themes kopiert werden.
Bei Twenty Eleven wäre das zum Beispiel /wp-content/themes/twentyeleven/google-plus-feed.php.

Für die Einrichtung des Feeds werden ein Google+ API Key sowie die Google+ User ID benötigt:

Google+ API Key

Wie jede API von Google benötigt auch die Google+ API einen API Key, welcher vorher generiert werden muss.

Google Plus API Console

Google+ API freischalten

Generiert kann sich dieser in der Google APIs Console unter code.google.com/apis/console/. Unter dem Tab Services muss dazu der zugehörige Regler auf On gesetzt werden.

Google+ User ID

Die User ID des Google+ Profils kann aus der jeweiligen URL zum Profil herausgefiltert werden, ein Beispiel:

https://plus.google.com/u/0/101675293278434581718/posts

101675293278434581718 wären in diesem Fall die User ID.

Einrichtung

Wenn API Key und User ID vorhanden sind, kann der Feed eingerichtet werden.
Dazu ins Backend wechseln und eine neue Seite einrichten, Titel und Inhalt (= Beschreibung des Feeds, ohne HTML Tags) festlegen und in der Metabox Attribute das Template Google+ Feed definieren.
Anschließend müssen der Key und die ID übergeben werden, dazu gibt es zwei Möglichkeiten:

  1. Die heruntergeladene Datei google-plus-feed.php öffnen und die Variablen private $user_id = ''; und private $api_key = '' mit den jeweiligen Werten belegen.
  2. Die zweite Möglichkeit geht über die benutzerdefinierten Feldern (ggf. über Reiter Optionen einblenden aktivieren). Dafür müssen zwei neue Felder angelegt werden, einmal gplus_feed_user_id mit dem Wert der User ID und einmal gplusfeed_api_key mit dem Wert des API Keys.

Speichern nicht vergessen und die Grundeinrichtung ist getan. Der Feed sollte jetzt erreichbar sein.

Zusätzliche Einstellungen

Weitere Anpassung an den RSS Feed können durch die Variable $this->settings getätigt werden. Dazu sollte sich die Methode set_settings() zu Rate gezogen werden.

/**
 * Set custom feed settings.
 *
 *  - limit: How many activities should be displayed in feed
 *  - cache_time: How long the feed should be cached
 *  - language: The language of the feed
 *  - update_period: See http://web.resource.org/rss/1.0/modules/syndication/
 *  - update_frequency: See http://web.resource.org/rss/1.0/modules/syndication/
 *
 * @since 0.1
 *
 * @return array Settings saved in an array.
 */
function set_settings() {
	$this->settings = wp_parse_args(
		array(
			'limit' => 10,
			'cache_time' => 300,
			'language' => 'de',
			'update_period' => 'hourly',
			'update_frequency' => 1
		),
		$this->settings
	);
}

Formatierung

Die Google+ API gibt als Titel nur die ersten paar Wörter aus.
Dies kann aber umgangen werden, wenn der Google+ Post mit einer in Fett formatierten Zeile gefolgt von zwei Absätzen beginnt, ein Bespiel:

Google Plus Feed Post Formatierung

Google+ Formatierung für die Feeddarstellung

Feedback

Feedback, Verbesserungsvorschläge, Probleme oder sonstige Fragen können gerne als Kommentar abgegeben werden und werden dort natürlich von mir beantwortet.

15 Kommentare zu WordPress Page Template für einen Google+ Feed

  1. Patrick

    Ich habe es nach Anleitung gemacht. In meinem Fall musste ich noch die Rechte setzen. Nun bekomme ich aber folgenden Fehler:

    Fatal error: Call to undefined function wp_trim_words() in /blabla/blablabla/webs/prod/homepage.de/www/wp-content/themes/magazine_ORDNER/google-plus-feed.php on line 284

    Da ich mich nicht so gut damit auskenne, frage ich mich, ob mir irgendwer weiterhelfen kann? Wäre super!

  2. Patrick

    Habe leider einen andere Fehler nun:
    Hier kann man es selber anschauen:

    weblog-deluxe.de/info/google-updates/

    Scheint mir auch irgendwie als wenn ein Beitrag von G+ doppelt angezeigt werden möchte?

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit einem * markiert.
Bitte bleibe beim Thema, für Supportanfragen stehe ich gerne per Mail zur Verfügung.

*

*