0

i want to set a cookie if a specified form (Contact Form 7) was sent.

If is write the code into the init-call it works:

function process_post() {
    
    if( isset( $_POST['kampagne'] ) ) {
        setcookie('cid', get_option( 'cf7-counter', 0) + 1 , time()+3600, '/'); 
    }
    
}
add_action( 'init', 'process_post' ); 

But that's not good, because the value of cookie is an id - stored in database, which i must get in the moment where the form will send.

So I want to set the cookie in the "wpcf7_before_send_mail" hook. But within that the cookie will not generate.

function wpcf7_do_something($WPCF7_ContactForm)
{
    
    $submission = WPCF7_Submission :: get_instance();
    
    if ( $submission ){

        $posted_data = $submission->get_posted_data();      
        if ( empty( $posted_data ) ){ return; }

        $changed_name = get_option( 'cf7-counter', 0) + 1;
        update_option('cf7-counter', $changed_name);

        $mail = $WPCF7_ContactForm->prop( 'mail' );

        $new_mail = str_replace( '[cf7-counter]', '00'. $changed_name .'', $mail );

        $WPCF7_ContactForm->set_properties( array( 'mail' => $new_mail ) );
        
        return $WPCF7_ContactForm;

    }
    
}
add_action("wpcf7_before_send_mail", "wpcf7_do_something");

I hope you can help me.

Thank you very much! Best regards.

1
  • 1
    Remember cookies are sent in headers, so if you have written anything other than headers to the browser, they will not be recieved. Is where you are doing this to late in the page building process?
    – RiggsFolly
    Commented Jul 3, 2021 at 9:04

1 Answer 1

0

But that's not good, because the value of cookie is an id - stored in database, which i must get in the moment where the form will send.

So what you need is the ID that will be stored into the database when creating the cookie.

Create it

if( isset( $_POST['kampagne'] ) ) {
    $cookie = 'cid';
    $id = uniqid("cid:", true);
    setcookie($cookie, $id, $_SERVER['REQUEST_TIME'] + HOUR_IN_SECONDS, '/', ini_get('session.cookie_domain'), (bool)ini_get('session.cookie_secure'), (bool)ini_get('session.cookie_httponly'));
    $_COOKIE[$cookie] = $id;
}

; and store it

$cookie = 'cid';
$WPCF7_ContactForm->set_properties(
  [
    'mail' => $new_mail,
    'cid' => $_COOKIE[$cookie],
  ]
);

.

The contact form transaction now has the id that is in the cookie.

It is independent to get_option( 'cf7-counter', 0) by binding the submission to its own identifier - like the cookie is not the cf7-counter option.

Take note on explicitly setting $_COOKIE[$cookie] = $id;, always. This is to have the ID in the request itself.

Take double note on this action, as the code does set the cookie with a new ID even if it was already set. If that is not your intention, check if the cookie is unset beforehand (later references on setting a cookie in Wordpress have it, too).


It is now more eventually consistent, up to the level of uniqueness of the uniquid() function (study it if you want to make use of it), which is an improvement over the situation where the chance of being inconsistent was much higher (that is when using the cf7-counter option).

An insecure random-unique ID normally is enough for short term transaction tagging, e.g. having it for an hour in the cookie.

Which is something you may want to put more of your attention to. And the example is less Wordpress specific, there is more to get from in Wordpress like nonces, keys, salts, cookie-paths, user-level cookies etc. pp. to adhere to that system specifically.

It requires you to study Wordpress first, which I can't take of your shoulders, and there is even more to learn first, like how cookies work. Perhaps ask the more general questions first that you have to close such gaps.


Another answer I was thinking about first is to take a more fitting action so that you have the id the moment you can do both: setting the cookie and storing to the database.

As it has been commented, such a solution would need to find the right place in time. But that is merely how cookies work.

(And not specifically Wordpress.)

As you have already seen yourself, the action you wanted to use did not work.

And even if you would find such another action, this is still Wordpress, and it would be unpredictable that it would suffice: The cookie might be set in your tests, but not when a user visits the site (or any site that is out there with Contact Form 7 which this answer should answer if it is worth it).

To set a cookie in Wordpress, there is no free choice of the action to do it in, but it first of all needs to set the cookie for which the action is invariant:

As the action is set in stone to set a cookie, this goes back to the answer above.

However this is not Wordpress SE, but Stackoverflow so I've put the focus more on the PHP code itself where it relates to the PHP configuration and only HOUR_IN_SECONDS is a constant from Wordpress in it. See as well my comment on it about more specific Wordpress features you may want to add to it.

It hopefully answers your question to the level you need it.

Not the answer you're looking for? Browse other questions tagged or ask your own question.