Alta de usuario desde Contact Form 7

Programación

Para un cliente he realizado un formulario de suscripción a una revista. En dicho formulario se recogen los datos típicos de nombre, apellidos, email, dirección de envío y, además, un número de cuenta y el dni.

Necesitaba que, una vez enviado el formulario y tras avisar a suscripciones y confirmar al propio usuario, se diera de alta a este como un nuevo perfil en WordPress llamado suscriptor revista que fuera similar al perfil de cliente de woocommerce, recogiendo además los datos extras de iban y dni.

Por un lado, he creado el perfil de usuario nuevo colocando este código en functions.php o en un plugin de funcionalidades

<?php
//Duplicamos las capabilities del perfil de cliente
$client = get_role('customer');
$suscriptor = add_role('suscriptor', 'Suscriptor Revista', $client->capabilities);

Una vez ejecutado y tras comprobar que el nuevo perfil se ha creado, he borrado el código. No lo necesito más. Si lo dejara, se ejecutaría cada vez que entro.

Luego procedemos a gestionar el tema de los campos extras de dni e iban

<?php
/**
 * Añadimos los campos dni e iban a la ficha de usuario
 */
add_action( 'show_user_profile', 'jpd_add_dni_iban_fields' );
add_action( 'edit_user_profile', 'jpd_add_dni_iban_fields' );
function jpd_add_dni_iban_fields( $user ) {
?>
    <h3>Información adicional</h3>
    <table class="form-table">
        <tr>
            <th><label for="dni">DNI</label></th>
            <td>
                <input type="text" name="dni" id="dni" value="<?php echo esc_attr( get_the_author_meta( 'dni', $user->ID ) ); ?>" class="regular-text" /><br />
                <span class="description">Por favor, introduce tu DNI.</span>
            </td>
        </tr>
        <tr>
            <th><label for="iban">IBAN</label></th>
            <td>
                <input type="text" name="iban" id="iban" value="<?php echo esc_attr( get_the_author_meta( 'iban', $user->ID ) ); ?>" class="regular-text" /><br />
                <span class="description">Por favor, introduce tu IBAN.</span>
            </td>
        </tr>
    </table>
<?php
}


/**
 * Añadimos los campos dni e iban a la ficha de mis datos en Mi Cuenta
 */
add_action( 'woocommerce_edit_account_form', 'jpd_show_dni_iban_fields_on_edit_account_page' );
function jpd_show_dni_iban_fields_on_edit_account_page() {
    $user = wp_get_current_user();

    $dni = get_user_meta( $user->ID, 'dni', true );
    $iban = get_user_meta( $user->ID, 'iban', true );
    ?>
    <p class="form-row form-row-wide">
        <label for="dni"><?php _e( 'DNI', 'woocommerce' ); ?></label>
        <input type="text" class="input-text" name="dni" id="dni" value="<?php echo esc_attr( $dni ); ?>" />
    </p>
    <p class="form-row form-row-wide">
        <label for="iban"><?php _e( 'IBAN', 'woocommerce' ); ?></label>
        <input type="text" class="input-text" name="iban" id="iban" value="<?php echo esc_attr( $iban ); ?>" />
    </p>
    <?php
}


/**
 * Guardamos los campos dni e iban al guardar el perfil de usuario
 */
add_action( 'personal_options_update', 'jpd_save_dni_iban_fields' );
add_action( 'edit_user_profile_update', 'jpd_save_dni_iban_fields' );
add_action( 'woocommerce_save_account_details', 'jpd_save_dni_iban_fields' );
function jpd_save_dni_iban_fields( $user_id ) {
    if ( !current_user_can( 'edit_user', $user_id ) )
        return false;

    update_user_meta( $user_id, 'dni', sanitize_text_field($_POST['dni']) );
    update_user_meta( $user_id, 'iban', sanitize_text_field($_POST['iban']) );
}

Hay tres hooks que usamos. Los habituales son los show_user_profile y edit_user_profile que son los relativos a la ficha de usuario de WordPress. Pero en este caso, como quiero que el usuario tambien pueda modificarlos desde su página de mi cuenta que proporciona WooCommerce, he añadido un tercer action, woocommerce_edit_account_form, que tiene un formato un poco distinto y que, por tanto, merece una función distinta.

Guardar los datos sí que comparten función porque al final se trata de utilizar la función update_user_meta para guardar el dato enviado, una vez sanitizado.

Finalmente, lo que necesitaba era una función que se ejecutara al guardar el formulario de Contact Form 7 y que creara el usuario con todos los datos del formulario. Es esta:

<?php
/**
 * Al guardar el formulario de contacto, creamos el usuario equivalente
 */
add_action( 'wpcf7_mail_sent', 'jpd_create_user_and_save_address_from_contact_form_7' );
function jpd_create_user_and_save_address_from_contact_form_7($cf7) {

    // Comprueba si el formulario es el id 2392
    if ( $cf7->id() != 2392 ) {
        return;
    }

    // Obtenemos los datos del formulario
    $submission = WPCF7_Submission::get_instance();
    if ( $submission ) {
        $posted_data = $submission->get_posted_data();
    }


    // Obtenemos los datos del formulario y los asignamos a variables
    $email = $posted_data['your-email'];
    $first_name = $posted_data['your-name'];
    $last_name = $posted_data['your-lastname'];
    $address = $posted_data['direccion'];
    $city = $posted_data['localidad'];
    $state = $posted_data['provincia'];
    $country = $posted_data['pais'];
    $phone = $posted_data['telefono'];
    $postcode = $posted_data['codigopostal'];
    $dni = $posted_data['dni'];
    $iban = $posted_data['cuenta'];

    // Comprobamos si el usuario existe
    $user = get_user_by('email', $email);
    if( !$user ) {
        // Generamos un nombre de usuario a partir del email
        $username = sanitize_user($email, true);

        // Creamos el nuevo usuario
        $user_id = wp_create_user($username, wp_generate_password(), $email);

        // Actualizamos en el nuevo usuario los datos de nombre, apellidos y display name
        wp_update_user(array(
            'ID' => $user_id,
            'first_name' => $first_name,
            'last_name' => $last_name,
            'display_name' => $first_name . ' ' . $last_name
        ));
    } else {
        //Si ya existía el usuario, simplemente recuperamos su ID
        $user_id = $user->ID;
    }

    // Asigna el perfil de suscriptor al usuario
    $user->set_role('suscriptor');

    // Actualizamos los datos específicos de WooCommerce: dirección de envío, dni e iban
    update_user_meta( $user_id, 'shipping_address_1', $address );
    update_user_meta( $user_id, 'shipping_city', $city );
    update_user_meta( $user_id, 'shipping_postcode', $postcode );
    update_user_meta( $user_id, 'shipping_country', $country );
    update_user_meta( $user_id, 'shipping_state', $state );
    update_user_meta( $user_id, 'shipping_first_name', $first_name );
    update_user_meta( $user_id, 'shipping_last_name', $last_name );
    update_user_meta( $user_id, 'billing_email', $email );
    update_user_meta( $user_id, 'shipping_phone', $phone );
    update_user_meta( $user_id, 'dni', $dni );
    update_user_meta( $user_id, 'iban', $iban );
}

Al principio de la función jpd_create_user_and_save_address_from_contact_form_7 tenemos un if que comprueba si el id del formulario es uno determinado (variará según el formulario). Si tenemos varios formularios de contact form 7, con esto nos aseguramos de que el formulario que vamos a procesar es el de suscripción a la revista y no otro.

Eso es todo. El usuario rellena el formulario de contact form 7, llegan los correos, se crea el usuario con el perfil de suscriptor de revista y quedan los datos ahí para que si el usuario quiere cambiar el iban o la dirección de envío, lo podrá hacer desde mi cuenta.

5 comentarios en «Alta de usuario desde Contact Form 7»

  1. Muy interesante, justo lo que estaba buscando. Esta solución me ha ahorrado instalar varios plugins. Me gustaría poder hacerlo para varios ids de formularios, sé que tendría que modificar estas líneas
    if ( $cf7->id() != 2392 ) {
    return;
    }
    pero no sé como hacerlo. ¿Podrías ayudarme?

    Responder
    • Hola:
      Me alegro mucho de que te sea útil.
      Lo que comentas yo creo que lo solucionaría algo así:
      $arrIdsValidos = array(2392, 2393, 2394);
      if ( !in_array($cf7->id(), $arrIdsValidos) ) {
      return;
      }

      Un abrazo,

      Responder
  2. Otro asunto que me está volviendo loca, ¿es normal que tenga que hacer clic dos veces en el botón del formulario para que se envíe? solo me pasa con el formulario al que he aplicado este código para el registro.

    Un saludo, gracias!

    Responder
    • Pues no tiene mucho sentido con el código este pues no hay nada que afecte al botón de envío, ningún javascript ni nada de eso. Todo corre en el back cuando ya se ha enviado el formulario.
      Se me ocurre que tengas algún javascript que esté causando algún error o alguna capa flotante encima del botón que no te esté dejando pulsarlo la primera vez…
      Pero ya te digo que no debería tener nada que ver con el código

      Responder

Deja un comentario