La API de opciones de WooCommerce (II)

Continuamos con la serie de API Settings para WooCommerce. Si te has perdido la primera parte, aquí la tienes: https://holadolly.wordpress.com/2014/05/13/la-api-de-opciones-de-woocommerce-i/

En el episodio anterior añadimos campos simples a nuestra pantalla de opciones en WooCommerce. Dichos campos son gestionados automáticamente sin necesitar de código adicional para su validación o HTML para mostrar los campos, WooCommerce se encargaba de todo.

Pero no todos los campos son simples, lo más probable es que en algún momento necesitemos mostrar campos más complejos que requieran un tratamiento especial. Afortunadamente, WooCommerce viene preparado para esto y con sólo unas líneas más podemos hacerlo sin complicar la cosa demasiado. Para ello tenemos que seguir unos pocos pasos:

  1. Decirle a WooCommerce que nuestro campo se tratará de forma diferente y mostrar el HTML del campo
  2. Validarlo ya que WooCommerce no lo hará por si mismo..

1. Agregar un campo personalizado y mostrarlo por pantalla

En la primera parte creamos una clase que se encargaría de mostrar/validar nuestra pestaña de opciones. Dicha clase contenía un método llamado get_settings() que devolvía un array con las opciones a mostrar y todas sus características. Ahora simplemente vamos a añadir un registro más a dicho array que contendrá la información de nuestro nuevo campo especial:


<?php
class WC_Settings_Hola_Dolly extends WC_Settings_Page {
public function __construct() {
$this->id = 'hola-dolly';
$this->label = __( 'Hola Dolly', 'hola-dolly' );
// Añadir pestaña
add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
// Mostrar los campos
add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
// Guardar los cambios
add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
}
public function get_settings() {
$settings = array(
array( 'title' => __( 'Opciones Generales', 'hola-dolly' ), 'type' => 'title', 'id' => 'holadolly_general_options', 'desc' => __( 'Nuestras opciones generales.', 'hola-dolly' ) ),
array(
'title' => __( 'Un número', 'hola-dolly' ),
'id' => 'holadolly_general_options_number',
'default' => 0,
'type' => 'number',
'desc_tip' => __( 'Pon un número por aquí', 'hola-dolly' )
),
array( 'type' => 'sectionend', 'id' => 'holadolly_general_options' ),
array( 'title' => __( 'Opciones Especiales', 'hola-dolly' ), 'type' => 'title', 'id' => 'holadolly_special_options', 'desc' => __( 'Nuestras opciones especiales.', 'hola-dolly' ) ),
// Aquí va nuestro campo especial encerrado en una nueva sección
array(
'title' => __( 'Campo especial', 'wookings' ),
'id' => 'holadolly_general_options_special',
'default' => '',
'type' => 'holadolly_special_field'
),
array( 'type' => 'sectionend', 'id' => 'holadolly_special_options' ),
);
return apply_filters( 'holadolly_woocommerce_holadolly_settings', $settings );
}
}
new WC_Settings_Hola_Dolly();

Como vemos, nuestro nuevo campo tiene una ID , holadolly_general_options_special y un tipo holadolly_special_field que no reconoce WooCommerce. Si refrescamos la pantalla no veremos nada nuevo. La nueva opción no se muestra por pantalla. WooCommerce necesita una función especial para dicho campo. Para ello necesitaremos dos cosas: un nuevo hook y una nueva función en nuestra clase:


<?php
class WC_Settings_Hola_Dolly extends WC_Settings_Page {
public function __construct() {
$this->id = 'hola-dolly';
$this->label = __( 'Hola Dolly', 'hola-dolly' );
// Añadir pestaña
add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
// Mostrar los campos
add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
// Guardar los cambios
add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
// Muestra nuestro campo especial
add_action( 'woocommerce_admin_field_holadolly_special_field', array( &$this, 'display_special_field' ) );
}
public function display_special_field( $field ) {
var_dump( $field );
}
public function get_settings() {
$settings = array(
array( 'title' => __( 'Opciones Generales', 'hola-dolly' ), 'type' => 'title', 'id' => 'holadolly_general_options', 'desc' => __( 'Nuestras opciones generales.', 'hola-dolly' ) ),
array(
'title' => __( 'Un número', 'hola-dolly' ),
'id' => 'holadolly_general_options_number',
'default' => 0,
'type' => 'number',
'desc_tip' => __( 'Pon un número por aquí', 'hola-dolly' )
),
array( 'type' => 'sectionend', 'id' => 'holadolly_general_options' ),
array( 'title' => __( 'Opciones Especiales', 'hola-dolly' ), 'type' => 'title', 'id' => 'holadolly_special_options', 'desc' => __( 'Nuestras opciones especiales.', 'hola-dolly' ) ),
// Aquí va nuestro campo especial encerrado en una nueva sección
array(
'title' => __( 'Campo especial', 'hola-dolly' ),
'id' => 'holadolly_general_options_special',
'default' => '',
'type' => 'holadolly_special_field'
),
array( 'type' => 'sectionend', 'id' => 'holadolly_special_options' ),
);
return apply_filters( 'holadolly_woocommerce_holadolly_settings', $settings );
}
}
new WC_Settings_Hola_Dolly();

Si nos fijamos, en el constructor de la clase hemos añadido un hook nuevo que se compone de la siguiente manera:

add_action( 'woocommerce_admin_field_$tipo_de_nuestro_campo', $funcion_que_muestra_el_campo );

El tipo de campo lo definimos ya en el array dentro de get_settings() y la función (o método) que se encarga de mostrarlo es display_special_field( $field ) que recibe como parámetro todos los atributos que definen el campo.

Para que veamos mejor qué contiene la variable  $field se la pasamos a var_dump:

01 woocommerce-ii

 

Básicamente, el contenido es el mismo que el del array en get_settings().

A partir de esta información vamos a recoger de Base de Datos el valor de nuestra opción y mostrarlo en un área de texto, que va a ser nuestro campo especial. La función display_special_field( $field ) queda de la siguiente manera:


<?php
public function display_special_field( $field ) {
$option_value = get_option( $field['id'], $field['default'] );
?>
<label for="<?php echo $field['id']; ?>" ><?php echo esc_html( $field['title'] ); ?></label><br/>
<textarea name="<?php echo $field['id']; ?>" id="<?php echo $field['id']; ?>"><?php echo esc_textarea( $option_value ); ?></textarea>
<?php
}

Gracias a get_option, recogemos el valor, si no lo encuentra tomará el valor que definimos en la propiedad default de nuestro campo. Luego generamos el código HTML para el área de texto cuya propiedad name será el ID del campo. Y ya está, lo podemos complicar todo lo que queramos pero el campo ya nos tiene que aparecer:

02 woocommerce-ii

 

Esto va bien pero si guardamos cambios, el valor del campo no se guarda en Base de Datos. ¡Toca validarlo!

 

2. Validación y guardado del campo especial

Como viene siendo costumbre, vamos a necesitar otro hook para que cuando WooCommerce haya terminado de guardar los campos, pase de nuevo por nuestra clase y guardemos el campo especial.

De manera similar al punto anterior, el hook tiene la siguiente composición:

add_action( "woocommerce_update_option_$tipo_de_campo", $funcion_que_valida_y_guarda_el_campo );

Así, nuestra clase queda tal que así:


<?php
class WC_Settings_Hola_Dolly extends WC_Settings_Page {
public function __construct() {
$this->id = 'hola-dolly';
$this->label = __( 'Hola Dolly', 'hola-dolly' );
// Añadir pestaña
add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
// Mostrar los campos
add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
// Guardar los cambios
add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
// Muestra nuestro campo especial
add_action( 'woocommerce_admin_field_holadolly_special_field', array( &$this, 'display_special_field' ) );
// Guarda nuestro campo especial
add_action( 'woocommerce_update_option_holadolly_special_field', array( $this, 'sanitize_special_field' ) );
}
public function display_special_field( $field ) {
$option_value = get_option( $field['id'], $field['default'] );
?>
<label for="<?php echo $field['id']; ?>" ><?php echo esc_html( $field['title'] ); ?></label><br/>
<textarea name="<?php echo $field['id']; ?>" id="<?php echo $field['id']; ?>"><?php echo esc_textarea( $option_value ); ?></textarea>
<?php
}
public function sanitize_special_field( $field ) {
$value = ! empty( $_POST[ $field['id'] ] ) ? stripslashes( $_POST[ $field['id'] ] ) : '';
update_option( $field['id'], $value );
}
public function get_settings() {
$settings = array(
array( 'title' => __( 'Opciones Generales', 'hola-dolly' ), 'type' => 'title', 'id' => 'holadolly_general_options', 'desc' => __( 'Nuestras opciones generales.', 'hola-dolly' ) ),
array(
'title' => __( 'Un número', 'hola-dolly' ),
'id' => 'holadolly_general_options_number',
'default' => 0,
'type' => 'number',
'desc_tip' => __( 'Pon un número por aquí', 'hola-dolly' )
),
array( 'type' => 'sectionend', 'id' => 'holadolly_general_options' ),
array( 'title' => __( 'Opciones Especiales', 'hola-dolly' ), 'type' => 'title', 'id' => 'holadolly_special_options', 'desc' => __( 'Nuestras opciones especiales.', 'hola-dolly' ) ),
// Aquí va nuestro campo especial encerrado en una nueva sección
array(
'title' => __( 'Campo especial', 'wookings' ),
'id' => 'holadolly_general_options_special',
'default' => '',
'type' => 'holadolly_special_field'
),
array( 'type' => 'sectionend', 'id' => 'holadolly_special_options' ),
);
return apply_filters( 'holadolly_woocommerce_holadolly_settings', $settings );
}
}
new WC_Settings_Hola_Dolly();

La función que valida el campo la hemos llamado sanitize_special_field( $field ) donde $field tiene exactamente el mismo valor que en el punto anterior; los atributos de nuestro campo. Sólo hay que limpiarlo un poco (con stripslashes) y guardarlo mediante update_option.

Ahora sí, nuestro flamante nuevo campo funciona a las mil maravillas:

03 woocommerce-ii

 

En resumen

La nueva API Settings de WooCommerce nos ofrece muchísima flexibilidad para crear una nueva pestaña de opciones dentro de WooCommerce. Es altamente recomendable que nuestras opciones estén bien integradas en el plugin ya que evitará futuros fallos y además mejorará la facilidad de uso del interfaz para los usuarios habituales de WooCommerce.

WooCommerce provee más hooks para poder personalizar las pestañas como por ejemplo añadir links de secciones debajo de las pestañas (tal y como las opciones de envío o Emails tienen) pero simplemente investigando un poco el código se puede sacar. No obstante en Hola Dolly estamos abiertos a cualquier duda o pregunta que pueda enriquecer esta entrada.

2 comentarios en “La API de opciones de WooCommerce (II)

    • Hola Marcos.

      Las opciones las guarda WooCommerce en la tabla wp_options. No recuerdo ahora el nombre exacto de la opción pero algo como woocommerce_settings o woocommerce_options.

Replica a Marcos Cancelar la respuesta