How to make simply “report” button on posts

I’m building up a video-site using wordpress. It embeds videos from different sites. I really need a simply “Report broken video”-button that saves the url in a database or emails it to me. I’ve searched through some plugins, but can’t find any that does the job. Do you guys know any simple and easy solution to this?

Thanks 🙂

1
1

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

Leave a Comment