Search code examples
wordpresswoocommercereviewcouponhook-wordpress

Generate WooCommerce coupon when comment review is approved


I'm trying to generate a coupon code for customer once his review comment in woocommerce product is approved. I have the whole code ready but once comment is approved nothing happen.

My code only works with comment_post hook but not with the comment_unapproved_to_approved hook. Any advice?

function action_comment_post_coupon(  $comment, $comment_ID, $comment_approved, $commentdata ) {  
if ( isset ( $commentdata['comment_author_email'] ) ) {
        // Get author email
        $author_email = $commentdata['comment_author_email'];
        
if ( is_email( $author_email ) ) {
            $value = random_int(100000, 999999);
            $customer = $comment->comment_author_email;
            $coupon_code = $value; // Code
            $amount = '20'; // Amount
            $discount_type = 'percent'; // Type: fixed_cart, percent, fixed_product, percent_product

            $coupon = array(
                'post_title' => $coupon_code,
                'post_content' => '',
                'post_status' => 'draft',
                'post_author' => 1,
                'post_type'     => 'shop_coupon'
            );

            $new_coupon_id = wp_insert_post( $coupon );

            // Add meta
            update_post_meta( $new_coupon_id, 'discount_type', $discount_type );
            update_post_meta( $new_coupon_id, 'coupon_amount', $amount );
            update_post_meta( $new_coupon_id, 'individual_use', 'yes' );
            update_post_meta( $new_coupon_id, 'customer_email', $author_email );
            update_post_meta( $new_coupon_id, 'product_ids',$product_ids );
            update_post_meta( $new_coupon_id, 'exclude_product_ids', '' );
            update_post_meta( $new_coupon_id, 'usage_limit', '1' );
            update_post_meta( $new_coupon_id, 'expiry_date', strtotime("+14 days") );
            update_post_meta( $new_coupon_id, 'apply_before_tax', 'yes' );
            update_post_meta( $new_coupon_id, 'free_shipping', 'no' );
            unset($product_ids);
    
        }
}
}   
add_action( 'comment_unapproved_to_approved', 'action_comment_post_coupon', 10, 4 );

Solution

  • "My code only works with comment_post hook but not with the comment_unapproved_to_approved hook"

    As you can see the comment_post hook contains 3 params

    /**
     * Fires immediately after a comment is inserted into the database.
     *
     * @since 1.2.0
     * @since 4.5.0 The `$commentdata` parameter was added.
     *
     * @param int        $comment_ID       The comment ID.
     * @param int|string $comment_approved 1 if the comment is approved, 0 if not, 'spam' if spam.
     * @param array      $commentdata      Comment data.
     */
    function action_comment_post( $comment_ID, $comment_approved, $commentdata ) {
        // Do something
    }
    add_action( 'comment_post', 'action_comment_post', 10, 3 );
    

    See: do_action( 'comment_post', int $comment_ID, int|string $comment_approved, array $commentdata )

    While the comment_unapproved_to_approved hook contains only 1 which is $comment, therefore just changing hookname is not enough.

    See: do_action( "comment_{$old_status}_to_{$new_status}", WP_Comment $comment )


    So to answer your question you get:

    /**
     * Fires when the comment status is in transition from one specific status to another.
     *
     * The dynamic portions of the hook name, `$old_status`, and `$new_status`,
     * refer to the old and new comment statuses, respectively.
     *
     * Possible hook names include:
     *
     *  - `comment_unapproved_to_approved`
     *  - `comment_spam_to_approved`
     *  - `comment_approved_to_unapproved`
     *  - `comment_spam_to_unapproved`
     *  - `comment_unapproved_to_spam`
     *  - `comment_approved_to_spam`
     *
     * @since 2.7.0
     *
     * @param WP_Comment $comment Comment object.
     */
    function action_comment_unapproved_to_approved( $comment ) {    
        // When isset
        if ( isset ( $comment->comment_author_email ) ) {
            // Get author email
            $author_email = $comment->comment_author_email;
                
            // Is email
            if ( is_email( $author_email ) ) {          
                // Get an emty instance of the WC_Coupon Object
                $coupon = new WC_Coupon();
        
                // Generate a non existing coupon code name
                $coupon_code = random_int( 100000, 999999 ); // OR generate_coupon_code();
                $discount_type = 'percent';
                $coupon_amount = '20'; // Amount
    
                // Set the necessary coupon data (since WC 3+)
                $coupon->set_code( $coupon_code );
                $coupon->set_discount_type( $discount_type );
                $coupon->set_amount( $coupon_amount );
                $coupon->set_individual_use( true );
                $coupon->set_usage_limit( 1 );
                $coupon->set_email_restrictions( array( $author_email ) );
                $coupon->set_date_expires( strtotime( '+14 days' ) );
                $coupon->set_free_shipping( true );
    
                // Create, publish and save coupon (data)
                $coupon->save();
            }
        }
    }
    add_action( 'comment_unapproved_to_approved', 'action_comment_unapproved_to_approved', 10, 1 );
    

    Note: since WooCommerce 3, your code is a bit outdated. Instead you should better use the available WC_Coupon setter methods.

    All information about this can be found via WC_Coupon