WOOT - WooCommerce Active Products Tables

Personalizar la ventana de variaciones de una tabla de productos WooCommerce

La ventana emergente de variaciones de una tabla de productos WooCommerce, la ventana que se abre cuando un visitante hace clic en select [5] junto a un producto variable, es una pequeña tabla de productos por derecho propio. Para personalizar la ventana de variaciones se cambia esa tabla: sus columnas, las filas por página, el orden, los campos adicionales y el aspecto. Una parte es un ajuste y el resto requiere unas pocas líneas de código. A continuación verás cada tarea, con el motivo por el que funciona así.

Cómo funciona la ventana de variaciones de una tabla de productos WooCommerce

Dos botones abren la ventana. En la columna Carrito (Cart), un producto variable recibe select [N] en lugar de un botón Añadir al carrito (Add to cart), y la columna Variaciones (Variations) muestra Var.[N], donde N es el número de variaciones. Ambos cargan la tabla [woot_variations] de ese producto.

  • La ventana no usa las columnas de la tabla desde la que se abrió. Sus columnas salen de WOOT → Ajustes (Settings) → Columnas de variaciones (Variations columns); de la tabla principal solo se hereda el aspecto (skin).
  • Todas las variaciones del producto se cargan a la vez y luego se paginan y ordenan en el navegador: 10 filas por página, paginación arriba, filas ordenadas alfabéticamente por la celda Título (Title). El título de una variación es el nombre del producto más los valores de sus atributos, y por eso las tallas salen como L, M, S, XL.
  • La ventana siempre es una tabla. Su diseño no se puede reemplazar con una plantilla, pero cualquier columna se puede cambiar o añadir.

Los cambios en código pasan por un solo filtro, woot_vurgc_shortcode_data. Se ejecuta para las tablas de variaciones, ventas adicionales, ventas cruzadas, agrupados y relacionados justo antes de dibujar la tabla y recibe todos sus argumentos: filter_provider es woot_variations para las variaciones, y filter_data['product_id'] contiene el producto. Los fragmentos antiguos usaban woot_review_shortcode_args, que filtra todas las tablas [woot] del sitio; usa el hook específico en su lugar. Todos los fragmentos siguientes van en el functions.php de un tema hijo o en un plugin de fragmentos de código.

Personalizar las columnas de la ventana de variaciones

Abre WOOT → Ajustes (Settings), busca Columnas de variaciones (Variations columns) y selecciona los campos que quieras; mantén pulsado un campo seleccionado para arrastrarlo a otra posición. La lista se aplica a todas las ventanas de variaciones y a todos los shortcodes [woot_variations] sin columnas propias. El botón Todas las claves de columnas posibles (All possible columns keys), bajo la tabla de ajustes, lista la clave de cada campo.

Una tabla de variaciones colocada en una página puede tener sus propias columnas: [woot_variations id=49 columns='thumbnail,pa_size,pa_color,price,add_to_cart'], donde id es el ID del producto. En la página de un producto individual se puede omitir el ID y se usa el producto actual; consulta cómo insertar shortcodes en la página de producto individual.

Dos detalles ahorran tiempo. Las columnas de atributo como pa_size muestran el valor de cada variación, y el título también incluye los valores de los atributos, pero solo en los atributos globales creados en Productos → Atributos. Los valores de los atributos personalizados escritos directamente en un producto no aparecen ni en el título ni como columna. Y el encabezado por defecto de una columna de atributo es el nombre de la taxonomía de WooCommerce, como Product Size; renómbralo con el Vocabulario.

Filas por página y paginación

En una página, usa el atributo per_page: [woot_variations id=49 per_page=4], o per_page=-1 para mostrar todas las variaciones sin paginación. Para la ventana emergente, define los mismos argumentos en el hook:

add_filter('woot_vurgc_shortcode_data', function ($args) {
    if (isset($args['filter_provider']) && $args['filter_provider'] === 'woot_variations') {
        $args['per_page'] = 20;           // -1 shows all variations
        $args['per_page_position'] = 'b'; // pagination: t, b, tb or none
    }
    return $args;
});

Cambiar el orden: por ID, por precio, como en el editor de productos

La ventana ordena las filas en el navegador según el contenido de una celda. Ordenar por ID funciona directamente, porque la celda del ID contiene un número simple:

add_filter('woot_vurgc_shortcode_data', function ($args) {
    if (isset($args['filter_provider']) && $args['filter_provider'] === 'woot_variations') {
        $args['orderby'] = 'id';
        $args['order'] = 'asc';
    }
    return $args;
});

Para que esto funcione, la columna ID debe estar entre las Columnas de variaciones (Variations columns), ya que las filas solo contienen los campos seleccionados; para mantenerla fuera de la vista, quítala de $args['columns'] en el mismo hook, como hace el siguiente ejemplo con su columna auxiliar. Ordenar por la columna Precio (Price) no da el resultado esperado: la celda del precio contiene HTML con formato y el símbolo de la moneda, así que los valores se comparan como texto y 105 queda antes que 12, y 12 antes que 9. La forma fiable es una columna auxiliar con el número sin formato, usada para ordenar y mantenida fuera de la vista:

// 1. A helper column with the price as a plain number
add_filter('woot_profile_extend', function ($profile, $action_name) {
    if ($action_name === 'woot_woocommerce_tables') {
        $profile['sort_price'] = [
            'title'   => 'Sort: price',
            'display' => false, // not offered in the Columns tab of regular tables
            'action'  => function ($post_id) {
                $product = WOOT_WooCommerce::get_product($post_id);
                return is_object($product) ? (float) $product->get_price() : 0;
            },
        ];
    }
    return $profile;
}, 10, 2);

// 2. Sort the popup by it and hide the helper column
add_filter('woot_vurgc_shortcode_data', function ($args) {
    if (isset($args['filter_provider']) && $args['filter_provider'] === 'woot_variations') {
        $args['orderby'] = 'sort_price';
        $args['order'] = 'asc'; // 'desc' puts the most expensive first
        $args['columns'] = implode(',', array_diff(explode(',', $args['columns']), ['sort_price']));
    }
    return $args;
});

Después de añadir el código, añade Sort: price a Columnas de variaciones (Variations columns) en Ajustes; de lo contrario, las filas no llevarán el número. Para el orden que defines arrastrando las variaciones en el editor de productos, usa el mismo patrón con una columna auxiliar que devuelva (int) get_post_field('menu_order', $post_id).

Mostrar campos personalizados de la variación y datos del producto principal

Los campos añadidos en la pestaña Meta pertenecen a una sola tabla, y la ventana emergente no tiene ID de tabla, así que nunca aparecen en Columnas de variaciones (Variations columns). Registra en su lugar la clave meta para todas las tablas, como se describe en cómo añadir una clave meta globalmente a todos los shortcodes:

add_filter('woot_profile_extend', function ($profile, $action_name) {
    if ($action_name === 'woot_woocommerce_tables') {
        $meta_key = 'msrp'; // the meta key of your variation field
        $profile[$meta_key] = woot()->columns->meta->assemble_meta_for_system([
            'title'     => WOOT_Vocabulary::get('MSRP'),
            'meta_key'  => $meta_key,
            'meta_type' => 'text', // text, number or calendar
        ]);
    }
    return $profile;
}, 10, 2);

La nueva columna aparece en Columnas de variaciones (Variations columns). En la ventana, cada fila lee el campo de la propia variación, de modo que un campo guardado por variación muestra su propio valor en cada fila.

Los datos del producto principal funcionan igual, porque una columna personalizada recibe el ID de la variación de esa fila. La columna integrada Miniatura (Thumbnail) muestra solo la imagen propia de la variación; esta columna muestra la imagen de la variación o, si no la tiene, la del producto, ya que WooCommerce recurre a la imagen del producto principal en las variaciones:

add_filter('woot_profile_extend', function ($profile, $action_name) {
    if ($action_name === 'woot_woocommerce_tables') {
        $profile['image_or_parent'] = [
            'title'  => WOOT_Vocabulary::get('Image'),
            'action' => function ($post_id) {
                $product = WOOT_WooCommerce::get_product($post_id);
                $image_id = is_object($product) ? $product->get_image_id() : 0;
                $src = $image_id ? wp_get_attachment_image_src($image_id, 'thumbnail') : false;
                return $src ? WOOT_HELPER::draw_html_item('img', ['src' => $src[0], 'width' => 60, 'alt' => '']) : '';
            },
        ];
    }
    return $profile;
}, 10, 2);

Para cualquier otro dato del producto principal, $product->get_parent_id() devuelve su ID.

Columnas distintas para distintos roles de usuario

El hook se ejecuta en cada petición de la ventana, así que puede comprobar quién está mirando. Esta versión oculta las columnas de SKU y de stock a todos salvo a un rol:

add_filter('woot_vurgc_shortcode_data', function ($args) {
    if (isset($args['filter_provider']) && $args['filter_provider'] === 'woot_variations') {
        $user = wp_get_current_user();
        if (!in_array('wholesale_customer', (array) $user->roles, true)) { // your role slug
            $args['columns'] = implode(',', array_diff(explode(',', $args['columns']), ['sku', 'stock_quantity']));
        }
    }
    return $args;
});

Se aplica una regla: las filas se preparan antes de que se ejecute el hook, a partir de los campos seleccionados en Ajustes. Por eso selecciona en Columnas de variaciones (Variations columns) todas las columnas que cualquier rol pueda ver, en el orden correcto, y quita columnas solo en el hook. Una columna añadida en el hook quedaría vacía, y una lista reordenada colocaría los encabezados sobre las celdas equivocadas.

Añadir al carrito y estilos

Cada fila tiene su propio campo de cantidad y su botón Añadir al carrito (Add to cart). Una variación sin precio o sin stock no recibe botón: WooCommerce no la considera comprable, y la tabla lo respeta. Un precio de 0 es un precio válido, así que el botón se mantiene. Para impedir que se compren variaciones con precio cero en cualquier lugar de la tienda, ventana emergente incluida:

add_filter('woocommerce_variation_is_purchasable', function ($purchasable, $variation) {
    if ((float) $variation->get_price() <= 0) {
        return false;
    }
    return $purchasable;
}, 10, 2);

En cuanto a los estilos, una tabla de variaciones colocada en una página tiene la misma estructura y las mismas clases que cualquier otra tabla, más la clase woot_variations_columns. Las tablas de las ventanas emergentes están dentro de .woot-content-in-popup. Cada celda tiene la clase table23_td_ más la clave del campo, y cada encabezado tiene un atributo data-key. La pestaña CSS personalizado (Custom CSS) de una tabla no llega a las ventanas emergentes, que no tienen ID de tabla, así que pon las reglas en el campo de CSS personalizado de tu tema:

/* Variations table on a page */
.woot_variations_columns .table23_td_price {
    font-weight: 600;
}

/* Tables in popups: variations, upsells, grouped */
.woot-content-in-popup th[data-key="stock_quantity"],
.woot-content-in-popup .table23_td_stock_quantity {
    text-align: center;
}

La ventana se solicita al servidor cada vez que se abre, así que los cambios en Ajustes y en el código se ven la próxima vez que un visitante pulse el botón. Las preguntas sobre una configuración concreta son bienvenidas en el foro de soporte de WOOT.