postmatic / epoch

WordPress commenting perfected.
38 stars 14 forks source link

Not working with the WP-reCAPTCHA plugin #37

Closed cadfile closed 9 years ago

cadfile commented 9 years ago

I had the WP-reCAPTCHA https://wordpress.org/plugins/wp-recaptcha/ plugin active on my site and I kept getting an error message "Your comment was not accepted please check that everything was filled out correctly" Deactivating that plugin then Epoch worked as expected.

WP-reCAPTCHA is an old plugin and all it does now is display the reCAPTCHA widget from Google.

https://developers.google.com/recaptcha/

Vernal commented 9 years ago

Thanks for letting us know. I haven't evaluated all of the various re-captcha plugins but am willing to bet you'll find one which is compatible. Let me know if you do not?

Jason

cadfile commented 9 years ago

Okay I will thanks

mihche commented 9 years ago

Hi, Could you please try GoodBye Captcha https://wordpress.org/plugins/goodbye-captcha I am the author and I've tested it with Epoch for a couple of days. It works as expected if don't choose "Override Completely" option for comment template. When Epoch uses iframe, it loads scripts earlier than GoodBye Captcha and the plugin is not working as expected. I've already figured out how to solve the issue and I'll have an update soon. Please let me know if you encounter any problem. Mihai

Shelob9 commented 9 years ago

@mihche What are the handles of the scripts that your plugin uses? I need to document how to load scripts inside the iFrame, and might as well use yours as an example.

mihche commented 9 years ago

Hi, As per Codex recommendation, I am using _wp_enqueuescripts hook. As I figured out, for iframe loading you are using _parsequery and _templateredirect hooks, which are called way earlier. That wouldn't be a problem but at the end of boot_epoch_front_comment function, if the "epoch" end point is present, you kill the php process, and... of course nothing after will be called. I think you came up with this solution in order to avoid theme's scripts and style sheets to load.

So... this is what I intend to do:

  1. Enqueue scripts earlier - using _parsequery or _templateredirect hooks
  2. Add action _epoch_iframefooter
  3. Add filter _epoch_iframescripts

I am working on this and I am not pretty sure that will work. I'll get back to you once I'll have the complete solution working.

Mihai

mihche commented 9 years ago

Hi Josh, This is what I've implemented and works in GoodBye Captcha

add_action('init', 'init_my_plugin');

function init_my_plugin(){
    //.....

    add_action('parse_query', 'load_epoch_iframe_scripts');

    //.....
}

function load_epoch_iframe_scripts($wp_query){
    /*
     * check if it's an Epoch endpoint request
     */
    if( !defined('EPOCH_VER') || !isset( $wp_query->query_vars['epoch']) || !is_singular())
        return;
    /*
     * register your script
     */
    wp_register_script('my_plugin_public-script', plugins_url( '/public/scripts/my-script.js', __FILE__ ));

    /*
     * localize your script if needed
     */
    wp_localize_script( 'my_plugin_public-script', 'object_name', array('value' => 10) );

    wp_enqueue_script('my_plugin_public-script');

    add_filter('epoch_iframe_scripts', array($this, 'register_epoch_scripts_handle'));
}

function register_epoch_scripts_handle($registered_scripts)
{
    if( !is_array($registered_scripts) )
        $registered_scripts = array();
    /*
     * add dependency if needed
     */
    $registered_scripts[] = 'jquery-core';
    /*
     * register your script handle
     */
    $registered_scripts[] = 'my_plugin_public-script';

    return $registered_scripts;
}

The only issue with the above solution is that the function epoch_iframe_footer_print_scripts located in /includes/functions.php, doesn't handle dependencies and if the plugins will add same scripts, like I did above with 'jquery-core', the script will be loaded multiple times. Probably, if you change the foreach loop with something like this, the problem is solved:

foreach( array_unique($scripts, SORT_STRING) as $handle ){
...
}

Am I missing something? Mihai

Vernal commented 9 years ago

Mihai!

Nice going jumping on this so quickly. I've updated our plugin page at http://gopostmatic.com/epoch to recommend GoodBye Captcha.

Thanks for being awesome, Jason

mihche commented 9 years ago

Thanks Jason, Really appreciate it! Mihai

Shelob9 commented 9 years ago

@mihche Thanks for showing how you did this.

I think your approach is a bit heavy-handed though. As long as your scripts are registered at wp_enqueue_scripts, you just need to add the handles to the array from epoch_iframe_scripts.

I don't see why you can't just do:

    add_filter( 'epoch_iframe_scripts', function( $handles ) {
        $my_script_handles  = array( 'georg', 'friedrich', 'handel' );
        if ( ! empty( $handles ) && is_array( $handles ) ) {
            $handles = array_merge( $handles, $my_script_handles );
        }else{
            $handles = $my_script_handles;
        }

        return $handles;

    });

BTW You are totally right that, since the script loader doesn't handle dependencies (a conscious decision,) it should filter out multiples of the same handle. I have opened #49 to address that.

mihche commented 9 years ago

@Shelob9 This is a nice solution, but I was trying to give a general one, with an example and without forcing other developers to use at least php 5.3 in order to load their scripts into iframe.

On the other hand, let me explain to you why I can't do only what you suggested if my scripts are registered at wp_enqueue_scripts

For iframe loading, the parse_query and template_redirect hooks are called.

            //load the front-end if on single post
            add_action( 'parse_query', array( $this, 'boot_epoch_front' ) );
            // inner comment
            add_filter( 'template_redirect', array( $this, 'boot_epoch_front_comment' ) );

Let's have a look at boot_epoch_front_comment' method

public function boot_epoch_front_comment( $template ) {
        global $wp_query;
        $this->front_stylescripts();
        if ( ! isset( $wp_query->query_vars['epoch'] ) || ! is_singular() ){
            return $template;
        }

        add_filter( 'show_admin_bar', '__return_false' );
        include EPOCH_PATH . 'includes/templates/comment-template.php';
        exit;
    }

The if statement is not satisfied, the file gets included and the php process is killed, and of course nothing after that will be executed. Until this point, the wp_enqueue_scripts action was never called by WP so... my scripts will never be rendered. That means, the latest point another plugin can load the scripts into Epoch' iframe is at template_redirect if is called with a priority less than 10, because Epoch uses priority 10 but can change it so... it is not recommended. Another option, which is safe, is to register the scripts at any point before the template_redirect is called, and I choose `parse_query`` because it is the first place where I can find out if the request is an Epoch endpoint.

I don't think that this will affect something but template_redirect is an action hook. add_filter( 'template_redirect', array( $this, 'boot_epoch_front_comment' ) ) should be add_action( 'template_redirect', array( $this, 'boot_epoch_front_comment' ) )

Cheers, Mihai

Shelob9 commented 9 years ago

@mihche

Good point on when wp_enqueue_scripts runs. Fixed via #51 Also you are correct that template_redirect is an action, not a filter, though all actions are filters. Still, you're right, fixed via #52.

BTW Plugin doesn't load on PHP 5.2, so I'm not worried about anonymous functions.