Basically, you filter 'the_content'
and add a button. Okay, it might be slightly more complicated:
- You need to send a mail per
wp_mail()
. - You need some spam protection: a hidden text field which should stay blank and a nonce field.
- You may want to restrict the pages where the button form will be displayed: On posts only or just on posts with a post format
video
. - I18n would be nice. 🙂
Since I needed exactly the same on my video blog, I’ve written a very simple plugin:
<?php # -*- coding: utf-8 -*-
/**
* Plugin Name: Report Broken Video
* Text Domain: plugin_rbv
* Domain Path: /lang
* Description: Adds a button to report broken videos
* Version: 2012.02.15
* Required: 3.3
* Author: Thomas Scholz
* Author URI: http://toscho.de
* License: GPL
*
*
* Report Broken Video, Copyright (C) 2012 Thomas Scholz
*
* 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 2 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.
*/
! defined( 'ABSPATH' ) and exit;
add_action( 'after_setup_theme', array ( 'Report_Broken_Video', 'init' ) );
class Report_Broken_Video
{
/**
* Internal variables prefix.
*
* @type string
*/
protected $prefix = 'rbv';
/**
* Name for a field that is hidden per CSS and filled by spammers only.
*
* @type string
*/
protected $hidden_field = 'no_fill';
/**
* URL of the current page.
*
* @see __construct()
* @type string
*/
protected $current_url="";
/**
* nonce = number used once, unique identifier for request validation.
*
* @type string
*/
protected $nonce_name="rbv_nonce";
/**
* On which post types do we want to show the form?
*
* @type array
*/
protected $post_types = array ( 'post' );
/**
* Creates a new instance. Called on 'after_setup_theme'.
*
* @see __construct()
* @return void
*/
public static function init()
{
new self;
}
/**
* Set actions, filters and basic variables, load language.
*
* @uses apply_filters() 'rbv_button' as action name
* 'rbv_auto_add_button' to append the form automatically
* 'rbv_post_types' for supported post types (default: 'post')
*/
public function __construct()
{
add_action( $this->prefix . '_button', array ( $this, 'print_button' ) );
$auto_add = apply_filters( $this->prefix . '_auto_add_button', TRUE );
$auto_add and add_filter( 'the_content', array ( $this, 'append_button' ), 50 );
$this->current_url = $_SERVER['REQUEST_URI'];
$this->post_types = apply_filters(
$this->prefix . '_post_types',
$this->post_types
);
$lang_loaded = load_plugin_textdomain(
'plugin_rbv',
FALSE,
basename( __DIR__ ) . '/lang'
);
}
/**
* Handler for the action 'rbv_button'. Prints the button.
*
* @return void
*/
public function print_button()
{
print $this->button_form();
}
/**
* Handler for content filter.
*
* @param string $content Existing content
* @return string
*/
public function append_button( $content )
{
return $content . $this->button_form();
}
/**
* Returns the button form or a feedback message after submit.
*
* @return string
*/
public function button_form()
{
if ( 'POST' != $_SERVER['REQUEST_METHOD'] )
{
return $this->get_form();
}
return $this->handle_submit();
}
/**
* Returns the form or an empty string.
*
* @uses apply_filters() 'rbv_show_form' to suppress form output.
* @return string
*/
public function get_form()
{
global $post;
if ( empty ( $post )
or ! in_array( get_post_type( $post ), $this->post_types )
// You may disable the form conditionally. For example: restrict it
// to posts with post-format 'video'.
or ! apply_filters( $this->prefix . '_show_form', TRUE, $post )
)
{
return '';
}
$post_id = (int) $post->ID;
$url = esc_attr( $this->current_url );
$hidden = $this->get_hidden_field();
$nonce = wp_create_nonce( __FILE__ );
$button_text = __( 'Report broken video', 'plugin_rbv' );
$form = <<<RBVFORM
<form method='post' action='$url' class="{$this->prefix}_form">
<input type="hidden" name="{$this->prefix}[$this->nonce_name]" value="$nonce" />
<input type="hidden" name="{$this->prefix}[post_id]" value="$post_id" />
<input type="submit" name="{$this->prefix}[report]" value="$button_text" />
</form>
RBVFORM;
return $form;
}
/**
* Hidden text field as spam protection.
*
* @return string
*/
protected function get_hidden_field()
{
// prevent doubled IDs if you use the_content() on archive pages.
static $counter = 0;
$field = $this->hidden_field . "_$counter";
$counter++;
$title = __( 'Leave this empty', 'plugin_rbv' );
return "<style scoped>#$field{display:none}</style>
<input name="{$this->prefix}[$field]" title="$title" />";
}
/**
* Handle form submission.
*
* @uses apply_filters() 'rbv_recipient' to set the mail recipient.
* 'rbv_from' to set the 'From' header.
* @return string
*/
protected function handle_submit()
{
if ( ! isset ( $_POST[ $this->prefix ] )
or '' == trim( implode( '', $_POST[ $this->prefix ] ) )
or ! wp_verify_nonce( $_POST[ $this->prefix ][ $this->nonce_name ], __FILE__ )
or ! empty ( $_POST[ $this->prefix ][ $this->hidden_field ] )
or empty ( $_POST[ $this->prefix ][ 'post_id' ] )
)
{
return $this->get_form();
}
$blog_name = get_bloginfo( 'name' );
$url = get_permalink( (int) $_POST[ $this->prefix ][ 'post_id' ] );
// Pro tempore. You may add an option for this in 'wp-admin'.
$recipient = get_option( 'admin_email' );
$recipient = apply_filters( $this->prefix . '_recipient', $recipient );
$subject = sprintf(
__( 'Broken video on %s', 'plugin_rbv' ),
$blog_name
);
$message = sprintf(
__( "There is a broken video on:\n <%s>", 'plugin_rbv' ),
$url
);
$from = "From: [RBV] $blog_name <$recipient>";
$from = apply_filters( $this->prefix . '_from', $from );
$send = wp_mail( $recipient, $subject, $message, $from );
$error = __(
'Sorry, we could not send the report. May we ask you to use the contact page instead?',
'plugin_rbv'
);
$success = __( "Thank you! We will take a look.", 'plugin_rbv' );
$feedback = $send ? $success : $error;
return "<p class="{$this->prefix}_result">$feedback</p>";
}
}
Update
Here is the GitHub repository: Plugin Report Broken Video.
Git clone URI: git://github.com/toscho/Report-Broken-Video.git