Conditional action hooks

Im developing an plugin that uses AJAX, but im having trouble controling the codeflow.

I want to hook functions after running conditionals. My hooks wont fire when adding them inside a control structure, but outside they fire.

I also have an event that fires an AJAX request, this can only happen after the user has triggered the event with an click, after all DOM is loaded. The AJAX request tells an PHP function to then set a cookie. It sets the cookie, but when reading the PHP docs about cookies, i see that they can only be set after any output is sent, but yet i managed to do this?

Ive read about the WordPress initialization sequence, but that didnt help me to solve this problem.

Heres my code:

add_action('wp_head', 'Init_');

function Init_(){
    if(isset($_COOKIE['user_opt'])){
        $user_opt = $_COOKIE['user_opt'];
        if($user_opt === 'out'){
            function user_checkout(){
                $ch_script_url = plugins_url('/js/check_out.js', __FILE__);
                wp_enqueue_script('checkout', $ch_script_url); 
            }
            add_action('wp_enqueue_scripts', 'user_checkout'); // load this if the cookie is set
        }
    } else { // run this otherwise
        function user_opt_handler(){
            $opt_script_url = plugins_url('/js/opt_handler.js', __FILE__);
            wp_enqueue_script('opt_handler', $opt_script_url, array('jquery'), TRUE);
            $nonce = wp_create_nonce('my_nonce');
            $ajax_url = admin_url('admin-ajax.php');

            wp_localize_script(
                'opt_handler',
                'options',
                array(
                    'check' => $nonce,
                    'ajax_url' => $ajax_url
                )
                );
        }

        function opt_box_html(){ ?>
        <div id="user-opt-box">
        <button id="user-choice-yes">Yes</button> <!-- the AJAX in the "opt_handler" script will fire when an click event for this button happens -->
        </div>
        <?php }

        function user_handler(){
            if(is_admin() === TRUE){
            check_ajax_referer('my_nonce');
            setcookie('user_opt', 'out');
            wp_die();
        }
    }
    add_action('wp_enqueue_scripts', 'user_opt_handler');
    add_action('wp_footer', 'opt_box_html', 100);
    add_action('wp_ajax_user_handler','user_handler');
    add_action('wp_ajax_nopriv_user_handler', 'user_handler'); 
  }
}

Ive also noticed that, when using php variables with normal (outside
all functions) scope, hooked functions dont have access to this.

For example, when trying to do this:

$a = "hello world";

function my_func(){
echo $a;
}

add_action('wp_footer', 'my_func');

This will output NULL. Is this because wordpress hooks only have access to variables declared inside them?

1 Answer
1

During page request, WordPress actions are triggered in a sequence, therefore you have to register them in time. In your case, wp_head comes after wp_enqueue_scripts, so as a solution, i would all remove them from the wp_head and register them all in a condition, outside of any other action:

if ( isset( $_COOKIE['user_opt'] ) ) {
    add_action('wp_enqueue_scripts', 'user_checkout');
    // ...
    // add relevant actions here if isset $_COOKIE['user_opt']
} else {
    add_action('wp_enqueue_scripts', 'user_opt_handler');
    // ...
    // add relevant actions here if not set
}

About the cookies. They are part of HTTP header, therefore they must be set before any output (not after as you stated above).

As for your second question. That’s nothing specific to WordPress, that’s standard behavior of callable. Please note, that callable might be specified differently:

// It might be anonymous function (closure)
add_action('wp_footer', function() {});

// A function
add_action('wp_footer', 'my_custom_function');

// Method call
add_action('wp_footer', [$obj, 'my_object_method']);

// and more...

And as you can see in the method call, that would be a way to get your context work with the function (assigning whatever values you want to $obj). As in $obj->a="hello world";

Leave a Comment