added Extra Feed Links 1.1

This commit is contained in:
Kenneth Reitz
2010-04-06 12:29:48 -04:00
parent d70d4bc7d3
commit c939dd2756
6 changed files with 779 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
<?php
if ( !class_exists('scbOptionsPage_07') )
require_once(dirname(__FILE__) . '/inc/scbOptionsPage.php');
class extraFeedLinkAdmin extends scbOptionsPage_07 {
protected function setup() {
$this->options = $GLOBALS['EFL_options'];
$this->defaults = array(
'home' => array(FALSE, '%site_title% Comments'),
'comments' => array(TRUE, 'Comments: %title%'),
'category' => array(TRUE, 'Category: %title%'),
'tag' => array(TRUE, 'Tag: %title%'),
'author' => array(TRUE, 'Author: %title%'),
'search' => array(TRUE, 'Search: %title%')
);
$this->args = array(
'page_title' => 'Extra Feed Links',
'short_title' => 'Extra Feed Links',
'page_slug' => 'extra-feed-links'
);
$this->nonce = 'efl-settings';
}
protected function form_handler() {
if ( empty($_POST['action']) )
return false;
check_admin_referer($this->nonce);
// Update options
if ( 'Save Changes' == $_POST['action'] ) {
foreach (array_keys($this->options->get()) as $name) {
$new_format[$name][0] = $_POST['show-' . $name];
$new_format[$name][1] = $_POST['format-' . $name];
}
$this->options->update($new_format);
$this->admin_msg('Settings <strong>saved</strong>.');
}
// Reset options
if ( 'Reset' == $_POST['action'] ) {
$this->options->reset();
$this->admin_msg('Settings <strong>reset</strong>.');
}
}
public function page_head() {
?>
<style type="text/css">
table input.widefat {width:250px !important}
</style>
<?php
}
public function page_content() {
echo $this->page_header();
?>
<p>The table below allows you to select which page types get an extra header link and the format of the link text.</p>
<div class="alignleft" style="width:auto">
<form method="post" action="">
<?php wp_nonce_field($this->nonce); ?>
<table class="widefat" style="width:auto">
<thead>
<tr>
<th scope="col" class="check-column"><input type="checkbox" /></th>
<th scope="col">Page type</th>
<th scope="col">Text format</th>
</tr>
</thead>
<tbody>
<?php foreach($this->options->get() as $name => $value) { ?>
<tr>
<th scope='row' class='check-column'><?php
echo $this->input(array(
'type' => 'checkbox',
'names' => 'show-'.$name,
'desc_pos' => 'none'
), array('show-'.$name => $value[0]));
?></th>
<td><?php echo ucfirst($name) ?></td>
<td><?php
echo $this->input(array(
'type' => 'text',
'names' => 'format-'.$name,
'desc_pos' => 'none'
), array('format-'.$name => $value[1]));
?></td>
</tr>
<?php } ?>
</tbody>
</table>
<div class="tablenav" style="width:auto">
<div class="alignleft">
<input name="action" type="submit" class="button-primary button" value="Save Changes" />
<input name="action" type="submit" class="button-secondary" onClick="return confirm('Are you sure you want to reset to defaults?')" value="Reset" />
</div>
</div>
</form>
</div>
<div style="float:left; margin-left: 50px">
<p>Available substitution tags:</p>
<ul>
<li><em>%title%</em> - displays the corresponding title for each page type</li>
<li><em>%site_title%</em> - displays the title of the site</li>
</ul>
</div>
<?php
echo $this->page_footer();
}
}
@@ -0,0 +1,189 @@
<?php
// Version 0.7.2
abstract class scbForms_07 {
/* Generates one or more input fields, with labels
$args = array (
'type' => any valid <input> type
'names' => string | array
'values' => string | array (default: 1 or $options['name'])
'check' => true | false (default: true)
'extra' => string (default: class="widefat")
'desc' => string (default: name)
'desc_pos' => 'before' | 'after' | 'none' (default: after)
);
$options = array('name' => 'value'...)
*/
public function input($args, $options = array()) {
$token = '%input%';
extract(wp_parse_args($args, array(
'desc_pos' => 'after',
'check' => true,
'extra' => 'class="widefat"'
)));
// Check required fields
if ( empty($type) )
trigger_error('No type specified', E_USER_WARNING);
if ( empty($names) ) {
trigger_error('No name specified', E_USER_WARNING);
return;
}
// Check for defined options
if ( $check && 'submit' != $type && !empty($options) )
self::check_names($names, $options);
$f1 = is_array($names);
$f2 = is_array($values);
// Set default values
if ( !isset($values) )
if ( 'text' == $type && !$f1 )
$values = stripslashes(wp_specialchars($options[$names], ENT_QUOTES));
elseif ( in_array($type, array('checkbox', 'radio')) )
$values = true;
// Expand names or values
if ( !$f1 && !$f2 )
$a = array($names => $values);
elseif ( $f1 && !$f2 )
$a = array_fill_keys($names, $values);
elseif ( !$f1 && $f2 )
$a = array_fill_keys($values, $names);
else
$a = array_combine($names, $values);
// Determine what goes where
if ( !$f1 && $f2 ) {
$i1 = 'val';
$i2 = 'name';
} else {
$i1 = 'name';
$i2 = 'val';
}
if ( $f1 || $f2 )
$l1 = 'name';
else
$l1 = 'desc';
// Generate output
foreach ( $a as $name => $val ) {
// Build extra string
$extra_s = $extra;
if ( in_array($type, array('checkbox', 'radio')) && $options[$$i1] == $$i2)
$extra_s .= " checked='checked'";
// Build the item
$input = "<input name='{$$i1}' value='{$$i2}' type='{$type}' {$extra_s}/> ";
// Add description
$desc = $$l1;
$desc = str_replace('[]', '', $desc);
if ( FALSE == stripos($desc, $token) )
if ( 'before' == $desc_pos )
$desc .= ' ' . $token;
elseif ( 'after' == $desc_pos )
$desc = $token . ' ' . $desc;
$desc = str_replace($token, $input, $desc);
$desc = trim($desc);
// Add label
if ( 'none' == $desc_pos || empty($desc) )
$output[] = $input . "\n";
else
$output[] = "<label for='{$$i1}'>{$desc}</label>\n";
}
return implode("\n", $output);
}
public static function select($args, $options) {
extract(wp_parse_args($args, array(
'name' => '',
'selected' => NULL,
'extra' => ''
)));
if ( empty($name) )
trigger_error('No name specified', E_USER_NOTICE);
if ( !is_array($options) ) {
trigger_error("Second argument is expected to be an associative array", E_USER_WARNING);
return;
}
foreach ( $options as $key => $value ) {
$extra_s = $extra;
if ( $name === $selected )
$extra_s = " selected='selected'";
else
$extra_s = "";
$opts .= "\t<option value='{$key}'{$extra_s}>{$value}</option>\n";
}
return "<select name='{$name}'>\n{$opts}</select>\n";
}
// Creates a textarea
public static function textarea($args, $content) {
extract(wp_parse_args($args, array(
'name' => '',
'extra' => 'class="widefat"',
'escaped' => 'false'
)));
if ( !$escaped )
$content = stripslashes(wp_specialchars($content, ENT_QUOTES));
if ( empty($name) )
trigger_error('No name specified', E_USER_NOTICE);
return "<textarea name='{$name}'{$extra}>\n{$content}\n</textarea>\n";
}
// Adds a form around the $content, including a hidden nonce field
public function form_wrap($content, $nonce = 'update_options') {
$output .= "\n<form method='post' action=''>\n";
$output .= $content;
$output .= wp_nonce_field($action = $nonce, $name = "_wpnonce", $referer = true , $echo = false);
$output .= "\n</form>\n";
return $output;
}
//_____HELPER METHODS (SHOULD NOT BE CALLED DIRECTLY)_____
// Checks if selected $names have equivalent in $options. Used by form_row()
protected static function check_names($names, $options) {
$names = (array) $names;
foreach ( $names as $i => $name )
$names[$i] = str_replace('[]', '', $name);
foreach ( array_diff($names, array_keys($options)) as $key )
trigger_error("Option not defined: {$key}", E_USER_WARNING);
}
}
// < PHP 5.2
if ( !function_exists('array_fill_keys') ) :
function array_fill_keys($keys, $value) {
$r = array();
foreach($keys as $key)
$r[$key] = $value;
return $r;
}
endif;
@@ -0,0 +1,67 @@
<?php
// Version 0.6
class scbOptions_06 {
public $key;
public $defaults;
private $data;
public function __construct($key) {
$this->key = $key;
$this->data = get_option($this->key);
}
public function setup($file, $defaults) {
$this->defaults = $defaults;
register_activation_hook($file, array($this, 'reset'), false);
register_uninstall_hook($file, array($this, 'delete'));
}
// Get all data or a certain field
public function get($field = '') {
if ( empty($field) === true )
return $this->data;
return @$this->data[$field];
}
// Update a portion of the data
public function update_part($newdata) {
if ( !is_array($this->data) || !is_array($newdata) )
return false;
$this->update(array_merge($this->data, $newdata));
}
// Update option
public function update($newdata) {
if ( $this->data === $newdata )
return;
$this->data = $newdata;
add_option($this->key, $this->data) or
update_option($this->key, $this->data);
}
// Reset option to defaults
public function reset($override = true) {
if ( !$override && is_array($this->defaults) && is_array($this->data) )
$newdata = array_merge($this->defaults, $this->data);
else
$newdata = $this->defaults;
$this->update($newdata);
}
// Delete option
public function delete() {
delete_option($this->key);
}
}
// < WP 2.7
if ( !function_exists('register_uninstall_hook') ) :
function register_uninstall_hook() {}
endif;
@@ -0,0 +1,195 @@
<?php
// Version 0.7.2
if ( ! class_exists('scbForms_07') )
require_once(dirname(__FILE__) . '/scbForms.php');
abstract class scbOptionsPage_07 extends scbForms_07 {
// Page args
protected $args = array(
'page_title' => '',
'short_title' => '',
'page_slug' => '',
'type' => 'settings'
);
// Hook string created at page init
protected $pagehook;
// Nonce string
protected $nonce;
// Plugin dir url
protected $plugin_url;
// scbOptions object holder
protected $options;
// Form actions
protected $actions = array();
//_____MAIN METHODS_____
// Main constructor
public function __construct($file = '') {
$this->set_url($file);
$this->setup();
$this->check_args();
if ( isset($this->options) )
$this->options->setup($file, $this->defaults);
add_action('admin_menu', array($this, 'page_init'));
}
// This is where all the page args goes
abstract protected function setup();
// This is where the css and js go
public function page_head() {}
// This is where the page content goes
abstract public function page_content();
// To be used in ::page_head()
protected function admin_msg($msg, $class = "updated") {
echo "<div class='$class fade'><p>$msg</p></div>\n";
}
// Wraps a string in a <script> tag
public function wrap_js($string) {
return "\n<script language='text/javascript'>\n" . $string . "\n</script>\n";
}
// Wraps a string in a <style> tag
public function wrap_css($string) {
return "\n<style type='text/css'>\n" . $string . "\n</style>\n";
}
// Generates a standard page head
protected function page_header() {
$this->form_handler();
echo "<div class='wrap'>\n";
echo "<h2>".$this->args['page_title']."</h2>\n";
}
// Generates a standard page footer
protected function page_footer() {
echo "</div>\n";
}
public function form_wrap($content) {
return parent::form_wrap($content, $this->nonce);
}
// Wrap a field in a table row
public function form_row($args, $options) {
return "\n<tr>\n\t<th scope='row'>{$args['title']}</th>\n\t<td>\n\t\t". parent::input($args, $options) ."\n\t</td>\n\n</tr>";
}
// Generates multiple rows and wraps them in a form table
protected function form_table($rows, $action = 'Save Changes') {
$output .= "\n<table class='form-table'>";
$options = $this->options->get();
foreach ( $rows as $row )
$output .= $this->form_row($row, $options);
$output .= "\n</table>\n";
$output .= $this->submit_button($action);
return parent::form_wrap($output, $this->nonce);
}
// Generates a submit form button
protected function submit_button($action = 'Save Changes', $class = "button") {
if ( in_array($action, $this->actions) )
trigger_error("Duplicate action for submit button: {$action}", E_USER_WARNING);
$args = array(
'type' => 'submit',
'names' => 'action',
'values' => $action,
'extra' => '',
'desc_pos' => 'none'
);
if ( ! empty($class) )
$args['extra'] = "class='{$class}'";
$this->actions[] = $action;
$output .= "<p class='submit'>\n";
$output .= parent::input($args);
$output .= "</p>\n";
return $output;
}
//_____HELPER METHODS (SHOULD NOT BE CALLED DIRECTLY)_____
// Checks and sets default args
protected function check_args() {
if ( empty($this->args['page_title']) )
trigger_error('Page title cannot be empty', E_USER_ERROR);
if ( empty($this->args['type']) )
$this->args['type'] = 'settings';
if ( empty($this->args['short_title']) )
$this->args['short_title'] = $this->args['page_title'];
if ( empty($this->args['page_slug']) )
$this->args['page_slug'] = sanitize_title_with_dashes($this->args['short_title']);
if ( empty($this->nonce) )
$this->nonce = $this->args['page_slug'];
}
// Registers a page
public function page_init() {
if ( !current_user_can('manage_options') )
return false;
extract($this->args);
if ( 'settings' == $type )
$this->pagehook = add_options_page($short_title, $short_title, 8, $page_slug, array($this, 'page_content'));
elseif ( 'tools' == $type )
$this->pagehook = add_management_page($short_title, $short_title, 8, $page_slug, array($this, 'page_content'));
else
trigger_error("Unknown page type: $page", E_USER_WARNING);
add_action('admin_print_styles-' . $this->pagehook, array($this, 'page_head'));
}
// Update options
protected function form_handler() {
if ( 'Save Changes' != $_POST['action'] )
return false;
check_admin_referer($this->nonce);
foreach ( $this->options->get() as $name => $value )
$new_options[$name] = $_POST[$name];
$this->options->update($new_options);
$this->admin_msg('Settings <strong>saved</strong>.');
}
// Set plugin_dir
protected function set_url($file) {
if ( function_exists('plugins_url') )
$this->plugin_url = plugins_url(plugin_basename(dirname($file)));
else
// < WP 2.6
$this->plugin_url = get_option('siteurl') . '/wp-content/plugins/' . plugin_basename(dirname($file));
}
}
+142
View File
@@ -0,0 +1,142 @@
<?php
/*
Plugin Name: Extra Feed Links
Version: 1.1.5.1
Description: Adds extra feed auto-discovery links to various page types (categories, tags, search results etc.).
Author: scribu
Author URI: http://scribu.net/
Plugin URI: http://scribu.net/wordpress/extra-feed-links
Copyright (C) 2009 scribu.net (scribu AT gmail DOT com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class extraFeedLink {
var $format;
var $format_name;
var $url;
var $title;
var $text;
function __construct() {
$this->format = $GLOBALS['EFL_options']->get();
add_action('wp_head', array($this, 'head_link'));
}
function head_link() {
$this->generate();
if( !$this->url || !$this->text )
return;
echo "\n" . '<link rel="alternate" type="application/rss+xml" title="' . $this->text . '" href="' . $this->url . '" />' . "\n";
}
function theme_link($input) {
$this->generate(TRUE);
if( !$this->url )
return;
if ( substr($input, 0, 4) == 'http' )
echo '<a href="' . $this->url . '" title="' . $this->text . '"><img src="' . $input . '" alt="rss icon" /></a>';
elseif ( $input == '' )
echo '<a href="' . $this->url . '" title="' . $this->text . '">' . $this->text . '</a>';
elseif ( $input == 'raw' )
echo $this->url;
else
echo '<a href="' . $this->url . '" title="' . $this->text . '">' . $input . '</a>';
}
function generate($for_theme = FALSE) {
$this->title = $this->url = NULL;
if ( is_home() && ($this->format['home'][0] || $for_theme) ) {
$this->url = get_bloginfo('comments_rss2_url');
$this->format_name = 'home';
}
elseif ( (is_single() || is_page()) && ($this->format['comments'][0] || $for_theme) ) {
global $post;
if ( $post->comment_status == 'open' ) {
$this->url = get_post_comments_feed_link($post->ID);
$this->title = $post->post_title;
$this->format_name = 'comments';
}
}
elseif ( is_category() && ($this->format['category'][0] || $for_theme) ) {
global $wp_query;
$cat_obj = $wp_query->get_queried_object();
$this->url = get_category_feed_link($cat_obj->term_id);
$this->title = $cat_obj->name;
$this->format_name = 'category';
}
elseif ( is_tag() && ($this->format['tag'][0] || $for_theme) ) {
global $wp_query;
$tag_obj = $wp_query->get_queried_object();
$this->url = get_tag_feed_link($tag_obj->term_id);
$this->title = $tag_obj->name;
$this->format_name = 'tag';
}
elseif ( is_author() && ($this->format['author'][0] || $for_theme) ) {
global $wp_query;
$author_obj = $wp_query->get_queried_object();
$this->url = get_author_feed_link($author_obj->ID);
$this->title = $author_obj->user_nicename;
$this->format_name = 'author';
}
elseif ( is_search() && ($this->format['search'][0] || $for_theme) ) {
$search = attribute_escape(get_search_query());
$this->url = get_search_feed_link($search);
$this->title = $search;
$this->format_name = 'search';
}
// Set the appropriate format
$this->text = $this->format[$this->format_name][1];
// Convert substitution tags
$this->text = str_replace('%title%', $this->title, $this->text);
$this->text = str_replace('%site_title%', get_option('blogname'), $this->text);
}
}
// Init
function efl_init() {
if ( !class_exists('scbOptions_06') )
require_once(dirname(__FILE__) . '/inc/scbOptions.php');
$GLOBALS['EFL_options'] = new scbOptions_06('efl-format');
$GLOBALS['extraFeedLink'] = new extraFeedLink();
if ( is_admin() ) {
require_once (dirname(__FILE__) . '/admin.php');
new extraFeedLinkAdmin(__FILE__);
}
}
efl_init();
remove_action('wp_head', 'feed_links_extra', 3);
// Template tag
function extra_feed_link($input = '') {
global $extraFeedLink;
$extraFeedLink->theme_link($input);
}
@@ -0,0 +1,66 @@
=== Extra Feed Links ===
Contributors: scribu
Donate link: http://scribu.net/wordpress
Tags: archive, comments, feed, rss, aton
Requires at least: 2.5
Tested up to: 2.8
Stable tag: 1.1.5.1
Adds extra feed auto-discovery links to various page types (categories, tags, search results etc.)
== Description ==
This plugin adds feed auto-discovery links to any page type:
* Category page
* Tag page
* Search page
* Author page
* Comments feed for single articles and pages
It also has a template tag that you can use in your theme.
== Installation ==
1. Unzip the archive and put the folder into your plugins folder (/wp-content/plugins/).
1. Activate the plugin from the Plugins admin menu.
1. Customize the links in the settings page.
**Usage**
You can use `extra_feed_link()` inside your theme to display a link to the feed corresponding to the type of page:
* `<?php extra_feed_link(); ?>` (creates a link with the default text)
* `<?php extra_feed_link('Link Text'); ?>` (creates a link with the text you choose)
* `<?php extra_feed_link('http://url/of/image'); ?>` (creates an image tag linked to the feed URL)
* `<?php extra_feed_link('raw'); ?>` (just displays the feed URL)
== Frequently Asked Questions ==
= "Parse error: syntax error, unexpected T_CLASS..." Help! =
Make sure your new host is running PHP 5. Add this line to wp-config.php:
`var_dump(PHP_VERSION);`
== Changelog ==
= 1.1.5 =
* WP 2.8 compatibility
= 1.1.1 =
* italian translation
= 1.1 =
* more flexible link text format
* [more info](http://scribu.net/wordpress/extra-feed-links/efl-1-1.html)
= 1.0 =
* added options page
= 0.6 =
* extra_feed_link() template tag
= 0.5 =
* initial release