Related
I'm using the following in function.php and it works great on a single product page. The issue I have is on the cart page when you choose a different quantity it doesn't automatically update the cart. Any ideas?
function woocommerce_quantity_input( $args = array(), $product = null, $echo = true ) {
if ( is_null( $product ) ) {
$product = $GLOBALS['product'];
}
$defaults = array(
'input_id' => uniqid( 'quantity_' ),
'input_name' => 'quantity',
'input_value' => '1',
'classes' => apply_filters( 'woocommerce_quantity_input_classes', array( 'input-text', 'qty', 'text' ), $product ),
'max_value' => apply_filters( 'woocommerce_quantity_input_max', -1, $product ),
'min_value' => apply_filters( 'woocommerce_quantity_input_min', 0, $product ),
'step' => apply_filters( 'woocommerce_quantity_input_step', 1, $product ),
'pattern' => apply_filters( 'woocommerce_quantity_input_pattern', has_filter( 'woocommerce_stock_amount', 'intval' ) ? '[0-9]*' : '' ),
'inputmode' => apply_filters( 'woocommerce_quantity_input_inputmode', has_filter( 'woocommerce_stock_amount', 'intval' ) ? 'numeric' : '' ),
'product_name' => $product ? $product->get_title() : '',
);
$args = apply_filters( 'woocommerce_quantity_input_args', wp_parse_args( $args, $defaults ), $product );
// Apply sanity to min/max args - min cannot be lower than 0.
$args['min_value'] = max( $args['min_value'], 0 );
// Change 6 to max quantity
$args['max_value'] = 0 < $args['max_value'] ? $args['max_value'] : 6;
// Max cannot be lower than min if defined.
if ( '' !== $args['max_value'] && $args['max_value'] < $args['min_value'] ) {
$args['max_value'] = $args['min_value'];
}
$options = '';
for ( $count = $args['min_value']; $count <= $args['max_value']; $count = $count + $args['step'] ) {
// Cart item quantity defined?
if ( '' !== $args['input_value'] && $args['input_value'] >= 1 && $count == $args['input_value'] ) {
$selected = 'selected';
} else $selected = '';
$options .= '<option value="' . $count . '"' . $selected . '>' . $count . '</option>';
}
$string = '<div class="quantity"><span>Qty</span><select name="' . $args['input_name'] . '">' . $options . '</select></div>';
if ( $echo ) {
echo $string;
} else {
return $string;
}
}
Caution: First you should never overwrite WooCommerce core files, for many reasons. So it's prohibited.
Instead as woocommerce_quantity_input() function call the template file global/quantity-input.php, you can override that template via your child theme.
To understand how to override templates, read carefully: Overriding templates via a theme in WooCommerce.
Now, remove all your related quantity changes and code from you web site (restore everything as before).
Then copy quantity-input.php file located inside WooCommerce plugin > templates > global, to your child theme into a "woocommerce" folder > "global" subfolder.
Once done, open / edit it, and replace the template content with:
<?php
/**
* Product quantity inputs
*
* This template can be overridden by copying it to yourtheme/woocommerce/global/quantity-input.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* #see https://docs.woocommerce.com/document/template-structure/
* #package WooCommerce\Templates
* #version 4.0.0
*/
defined( 'ABSPATH' ) || exit;
if ( $max_value && $min_value === $max_value ) {
?>
<div class="quantity hidden">
<input type="hidden" id="<?php echo esc_attr( $input_id ); ?>" class="qty" name="<?php echo esc_attr( $input_name ); ?>" value="<?php echo esc_attr( $min_value ); ?>" />
</div>
<?php
} else {
/* translators: %s: Quantity. */
$label = ! empty( $args['product_name'] ) ? sprintf( esc_html__( '%s quantity', 'woocommerce' ), wp_strip_all_tags( $args['product_name'] ) ) : esc_html__( 'Quantity', 'woocommerce' );
?>
<div class="quantity">
<?php do_action( 'woocommerce_before_quantity_input_field' ); ?>
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_attr( $label ); ?></label>
<?php
if ( is_cart() ) :
?>
<input
type="hidden"
id="<?php echo esc_attr( $input_id ); ?>"
class="<?php echo esc_attr( join( ' ', (array) $classes ) ); ?>"
name="<?php echo esc_attr( $input_name ); ?>"
value="<?php echo esc_attr( $input_value ); ?>"
title="<?php echo esc_attr_x( 'Qty', 'Product quantity input tooltip', 'woocommerce' );
?>" />
<?php
endif;
$options = ''; // Initializing
for ( $i = $min_value; $i <= $max_value; $i += $step ) :
$selected = ( '' !== $input_value && $input_value >= 1 && $i == $input_value ) ? 'selected' : '';
$options .= '<option value="' . $i . '"' . $selected . '>' . $i . '</option>';
endfor;
// Change input name on select field
$attr_name = is_cart() ? 'data-name' : 'name';
?>
<select <?php echo $attr_name; ?>="<?php echo $input_name; ?>"><?php echo $options; ?></select>
<?php do_action( 'woocommerce_after_quantity_input_field' ); ?>
</div>
<?php
}
Now some jQuery code is required, to make things work on cart page.
// jQuery - cart jQuery script for quantity dropdown
add_action( 'woocommerce_after_cart', 'cart_quantity_dropdown_js' );
function cart_quantity_dropdown_js() {
?>
<script type="text/javascript">
jQuery( function($){
$(document.body).on('change blur', 'form.woocommerce-cart-form .quantity select', function(e){
var t = $(this), q = t.val(), p = t.parent();
$(this).parent().find('input').val($(this).val());
console.log($(this).parent().find('input').val());
});
});
</script>
<?php
}
This code goes in functions.php file of the active child theme (or active theme).
Now to restrict the max quantity to 6, add the following code:
// Restricting product max quantity to 6
add_filter( 'woocommerce_quantity_input_args', 'woocommerce_quantity_input_args_callback', 10, 2 );
function woocommerce_quantity_input_args_callback( $args, $product ) {
$args['max_value'] = 6;
return $args;
}
// Restricting product variation max quantity to 6
add_filter( 'woocommerce_available_variation', 'filter_woocommerce_available_variation', 10, 3);
function filter_woocommerce_available_variation( $data, $product, $variation ) {
$data['max_qty'] = 6;
return $data;
}
This code goes in functions.php file of the active child theme (or active theme).
Now it works everywhere (tested on last WooCommerce version under Storefront theme).
The default WooCommerce Add to Cart “Quantity Input” is a simple input field where you can enter the number of items or click on the “+” and “-” to increase/reduce the quantity.
To let the users choose the quantity from a drop-down instead of having to manually input the number. This can be done using woocommerce_quantity_input function. Simply add the following Snippet to your Functions.php.
function woocommerce_quantity_input( $args = array(), $product = null, $echo = true ) {
if ( is_null( $product ) ) {
$product = $GLOBALS['product'];
}
$defaults = array(
'input_id' => uniqid( 'quantity_' ),
'input_name' => 'quantity',
'input_value' => '1',
'classes' => apply_filters( 'woocommerce_quantity_input_classes', array( 'input-text', 'qty', 'text' ), $product ),
'max_value' => apply_filters( 'woocommerce_quantity_input_max', -1, $product ),
'min_value' => apply_filters( 'woocommerce_quantity_input_min', 0, $product ),
'step' => apply_filters( 'woocommerce_quantity_input_step', 1, $product ),
'pattern' => apply_filters( 'woocommerce_quantity_input_pattern', has_filter( 'woocommerce_stock_amount', 'intval' ) ? '[0-9]*' : '' ),
'inputmode' => apply_filters( 'woocommerce_quantity_input_inputmode', has_filter( 'woocommerce_stock_amount', 'intval' ) ? 'numeric' : '' ),
'product_name' => $product ? $product->get_title() : '',
);
$args = apply_filters( 'woocommerce_quantity_input_args', wp_parse_args( $args, $defaults ), $product );
$args['min_value'] = max( $args['min_value'], 0 );
$args['max_value'] = 0 < $args['max_value'] ? $args['max_value'] : 20;
if ( '' !== $args['max_value'] && $args['max_value'] < $args['min_value'] ) {
$args['max_value'] = $args['min_value'];
}
$options = '';
for ( $count = $args['min_value']; $count <= $args['max_value']; $count = $count + $args['step'] ) {
if ( '' !== $args['input_value'] && $args['input_value'] >= 1 && $count == $args['input_value'] ) {
$selected = 'selected';
} else $selected = '';
$options .= '<option value="' . $count . '"' . $selected . '>' . $count . '</option>';
}
$string = '<div class="quantity"><span>Qty</span><select name="' . $args['input_name'] . '">' . $options . '</select></div>';
if ( $echo ) {
echo $string;
} else {
return $string;
}
}
I am trying to add a widget to Woocommerce to Filter Products by Quantity with a slider. I got this far by changing the open source code of woocommerce for the price filter slider. It print no errors once it's on the website but it does not filter the results. The output on the URL is also as expected. The slider does not work but it's fine if I cannot fix it. As of now it has two type-in fields: max and min stock quantity. Please help. I am sure others will benefit from this. I need it because the website is for wholesale and if a product is not available is a min quantity that a client wants, they can filter it out.
// Register and load the widget
function my_stock_widget() {
register_widget( 'WC_Widget_Stock_Filter' );
}
add_action( 'widgets_init', 'my_stock_widget' );
class WC_Widget_Stock_Filter extends WC_Widget {
/**
* Constructor.
*/
public function __construct() {
$this->widget_cssclass = 'woocommerce widget_stock_filter';
$this->widget_description = __( 'Shows a stock filter slider in a widget which lets you narrow down the list of shown products when viewing product categories.', 'woocommerce' );
$this->widget_id = 'woocommerce_stock_filter';
$this->widget_name = __( 'WooCommerce stock filter', 'woocommerce' );
$this->settings = array(
'title' => array(
'type' => 'text',
'std' => __( 'Filter by stock', 'woocommerce' ),
'label' => __( 'Title', 'woocommerce' ),
),
);
$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
wp_register_script( 'accounting', WC()->plugin_url() . '/assets/js/accounting/accounting' . $suffix . '.js', array( 'jquery' ), '0.4.2' );
wp_register_script( 'wc-jquery-ui-touchpunch', WC()->plugin_url() . '/assets/js/jquery-ui-touch-punch/jquery-ui-touch-punch' . $suffix . '.js', array( 'jquery-ui-slider' ), WC_VERSION, true );
wp_register_script( 'wc-stock-slider', WC()->plugin_url() . '/assets/js/frontend/price-slider' . $suffix . '.js', array( 'jquery-ui-slider', 'wc-jquery-ui-touchpunch', 'accounting' ), WC_VERSION, true );
wp_localize_script( 'wc-stock-slider', 'woocommerce_stock_slider_params', array(
'min_stock' => isset( $_GET['min_stock'] ) ? esc_attr( $_GET['min_stock'] ) : '',
'max_stock' => isset( $_GET['max_stock'] ) ? esc_attr( $_GET['max_stock'] ) : '',
'currency_format_num_decimals' => 0,
// 'currency_format_symbol' => get_woocommerce_currency_symbol(),
'currency_format_decimal_sep' => esc_attr( wc_get_price_decimal_separator() ),
'currency_format_thousand_sep' => esc_attr( wc_get_price_thousand_separator() ),
// 'currency_format' => esc_attr( str_replace( array( '%1$s', '%2$s' ), array( '%s', '%v' ), get_woocommerce_stock_format() ) ),
) );
parent::__construct();
}
/**
* Output widget.
*
* #see WP_Widget
*
* #param array $args
* #param array $instance
*/
public function widget( $args, $instance ) {
global $wp, $wp_the_query;
if ( ! is_post_type_archive( 'product' ) && ! is_tax( get_object_taxonomies( 'product' ) ) ) {
return;
}
if ( ! $wp_the_query->post_count ) {
return;
}
$min_stock = isset( $_GET['min_stock'] ) ? esc_attr( $_GET['min_stock'] ) : '';
$max_stock = isset( $_GET['max_stock'] ) ? esc_attr( $_GET['max_stock'] ) : '';
wp_enqueue_script( 'wc-stock-slider' );
// Find min and max stock in current result set
$stocks = $this->get_filtered_stock();
$min = floor( $stocks->min_stock );
$max = ceil( $stocks->max_stock );
if ( $min === $max ) {
return;
}
$this->widget_start( $args, $instance );
if ( '' === get_option( 'permalink_structure' ) ) {
$form_action = remove_query_arg( array( 'page', 'paged' ), add_query_arg( $wp->query_string, '', home_url( $wp->request ) ) );
} else {
$form_action = preg_replace( '%\/page/[0-9]+%', '', home_url( trailingslashit( $wp->request ) ) );
}
/**
* Adjust max if the store taxes are not displayed how they are stored.
* Min is left alone because the product may not be taxable.
* Kicks in when stocks excluding tax are displayed including tax.
*
if ( wc_tax_enabled() && 'incl' === get_option( 'woocommerce_tax_display_shop' ) && ! wc_stocks_include_tax() ) {
$tax_classes = array_merge( array( '' ), WC_Tax::get_tax_classes() );
$class_max = $max;
foreach ( $tax_classes as $tax_class ) {
if ( $tax_rates = WC_Tax::get_rates( $tax_class ) ) {
$class_max = $max + WC_Tax::get_tax_total( WC_Tax::calc_exclusive_tax( $max, $tax_rates ) );
}
}
$max = $class_max;
}*/
echo '<form method="get" action="' . esc_url( $form_action ) . '">
<div class="stock_slider_wrapper">
<div class="stock_slider" style="display:none;"></div>
<div class="stock_slider_amount">
<input type="text" id="min_stock" name="min_stock" value="' . esc_attr( $min_stock ) . '" data-min="' . esc_attr( apply_filters( 'woocommerce_stock_filter_widget_min_amount', $min ) ) . '" placeholder="' . esc_attr__( 'Min stock', 'woocommerce' ) . '" />
<input type="text" id="max_stock" name="max_stock" value="' . esc_attr( $max_stock ) . '" data-max="' . esc_attr( apply_filters( 'woocommerce_stock_filter_widget_max_amount', $max ) ) . '" placeholder="' . esc_attr__( 'Max stock', 'woocommerce' ) . '" />
<button type="submit" class="button">' . esc_html__( 'Filter', 'woocommerce' ) . '</button>
<div class="stock_label" style="display:none;">
' . esc_html__( 'Stock:', 'woocommerce' ) . ' <span class="from"></span> — <span class="to"></span>
</div>
' . wc_query_string_form_fields( null, array( 'min_stock', 'max_stock' ), '', true ) . '
<div class="clear"></div>
</div>
</div>
</form>';
$this->widget_end( $args );
}
/**
* Get filtered min stock for current products.
* #return int
*/
protected function get_filtered_stock() {
global $wpdb, $wp_the_query;
$args = $wp_the_query->query_vars;
$tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
$meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
if ( ! is_post_type_archive( 'product' ) && ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) {
$tax_query[] = array(
'taxonomy' => $args['taxonomy'],
'terms' => array( $args['term'] ),
'field' => 'slug',
);
}
foreach ( $meta_query + $tax_query as $key => $query ) {
if ( ! empty( $query['stock_filter'] ) || ! empty( $query['rating_filter'] ) ) {
unset( $meta_query[ $key ] );
}
}
$meta_query = new WP_Meta_Query( $meta_query );
$tax_query = new WP_Tax_Query( $tax_query );
$meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
$tax_query_sql = $tax_query->get_sql( $wpdb->posts, 'ID' );
$sql = "SELECT min( FLOOR( stock_meta.meta_value ) ) as min_stock, max( CEILING( stock_meta.meta_value ) ) as max_stock FROM {$wpdb->posts} ";
$sql .= " LEFT JOIN {$wpdb->postmeta} as stock_meta ON {$wpdb->posts}.ID = stock_meta.post_id " . $tax_query_sql['join'] . $meta_query_sql['join'];
$sql .= " WHERE {$wpdb->posts}.post_type IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_stock_filter_meta_keys', array( 'product' ) ) ) ) . "')
AND {$wpdb->posts}.post_status = 'publish'
AND stock_meta.meta_key IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_stock_filter_meta_keys', array( '_stock' ) ) ) ) . "')
AND stock_meta.meta_value > '' ";
$sql .= $tax_query_sql['where'] . $meta_query_sql['where'];
if ( $search = WC_Query::get_main_search_query_sql() ) {
$sql .= ' AND ' . $search;
}
return $wpdb->get_row( $sql );
}
I am trying to implement quantity dropdown for my woocommerce shop, i found the code below to enable for single products but I cannot get it working for products with variations.
<?php
// Place the following code in your theme's functions.php file
// override the quantity input with a dropdown
// Note that you still have to invoke this function like this:
/*
$product_quantity = woocommerce_quantity_input( array(
'input_name' => "cart[{$cart_item_key}][qty]",
'input_value' => $cart_item['quantity'],
'max_value' => $_product->backorders_allowed() ? '' : $_product->get_stock_quantity(),
'min_value' => '0'
), $_product, false );
*/
function woocommerce_quantity_input($data) {
global $product;
$defaults = array(
'input_name' => $data['input_name'],
'input_value' => $data['input_value'],
'max_value' => apply_filters( 'woocommerce_quantity_input_max', '', $product ),
'min_value' => apply_filters( 'woocommerce_quantity_input_min', '', $product ),
'step' => apply_filters( 'woocommerce_quantity_input_step', '1', $product ),
'style' => apply_filters( 'woocommerce_quantity_style', 'float:left; margin-right:10px;', $product )
);
if ( ! empty( $defaults['min_value'] ) )
$min = $defaults['min_value'];
else $min = 1;
if ( ! empty( $defaults['max_value'] ) )
$max = $defaults['max_value'];
else $max = 20;
if ( ! empty( $defaults['step'] ) )
$step = $defaults['step'];
else $step = 1;
$options = '';
for ( $count = $min; $count <= $max; $count = $count+$step ) {
$selected = $count === $defaults['input_value'] ? ' selected' : '';
$options .= '<option value="' . $count . '"'.$selected.'>' . $count . '</option>';
}
echo '<div class="quantity_select" style="' . $defaults['style'] . '"><select name="' . esc_attr( $defaults['input_name'] ) . '" title="' . _x( 'Qty', 'Product quantity input tooltip', 'woocommerce' ) . '" class="qty">' . $options . '</select></div>';
}
?>
The result I am after is something like this image:
How can this be done with Woocommerce?
Here's an updated version of woocommerce_quantity_input()
/**
* Output the quantity input for add to cart forms.
*
* #param array $args Args for the input
* #param WC_Product|null $product
* #param boolean $echo Whether to return or echo|string
*/
function woocommerce_quantity_input( $args = array(), $product = null, $echo = true ) {
if ( is_null( $product ) ) {
$product = $GLOBALS['product'];
}
$defaults = array(
'input_name' => 'quantity',
'input_value' => '1',
'max_value' => apply_filters( 'woocommerce_quantity_input_max', '20', $product ),
'min_value' => apply_filters( 'woocommerce_quantity_input_min', '0', $product ),
'step' => apply_filters( 'woocommerce_quantity_input_step', '1', $product ),
'pattern' => apply_filters( 'woocommerce_quantity_input_pattern', has_filter( 'woocommerce_stock_amount', 'intval' ) ? '[0-9]*' : '' ),
'inputmode' => apply_filters( 'woocommerce_quantity_input_inputmode', has_filter( 'woocommerce_stock_amount', 'intval' ) ? 'numeric' : '' ),
);
$args = apply_filters( 'woocommerce_quantity_input_args', wp_parse_args( $args, $defaults ), $product );
// Set min and max value to empty string if not set.
$args['min_value'] = isset( $args['min_value'] ) ? $args['min_value'] : '1';
$args['max_value'] = isset( $args['max_value'] ) ? $args['max_value'] : '20';
// Apply sanity to min/max args - min cannot be lower than 0
if ( '' !== $args['min_value'] && is_numeric( $args['min_value'] ) && $args['min_value'] < 0 ) {
$args['min_value'] = 0; // Cannot be lower than 0
}
// Max cannot be lower than 0 or min
if ( '' !== $args['max_value'] && is_numeric( $args['max_value'] ) ) {
$args['max_value'] = $args['max_value'] < 0 ? 0 : $args['max_value'];
$args['max_value'] = $args['max_value'] < $args['min_value'] ? $args['min_value'] : $args['max_value'];
}
ob_start();
$options = '';
for ( $count = $args['min_value']; $count <= $args['max_value']; $count = $count + $args['step'] ) {
$options .= '<option value="' . $count . '"'. selected( $count, $args['input_value'], false ) .'>' . $count . '</option>';
}
echo '<div class="quantity_select" style="' . $args['style'] . '"><select name="' . esc_attr( $args['input_name'] ) . '" title="' . _x( 'Qty', 'Product quantity input tooltip', 'woocommerce' ) . '" class="qty">' . $options . '</select></div>';
if ( $echo ) {
echo ob_get_clean();
} else {
return ob_get_clean();
}
}
Turns out the best way of doing this was to use grouped products
I currently have the 'Our Team' plugin installed to display team members.
At the moment, the staff description (that appears in the WISYWIG editor area), is pulled through onto the team page along with all the other staff details.
As there is quite a bit of text for each, i would like to have it so that there is just a 'Read about me' link, and the description text appears in a lightbox instead.
I already have a Lightbox plugin in use on the website (WP Lightbox 2), but just need to know how i can change the 'Our Team' template file so that it displays the link rather than the whole block of text.
Below is the 'woothemes-our-team-template.php' file:
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! function_exists( 'woothemes_get_our_team' ) ) {
/**
* Wrapper function to get the team members from the Woothemes_Our_Team class.
* #param string/array $args Arguments.
* #since 1.0.0
* #return array/boolean Array if true, boolean if false.
*/
function woothemes_get_our_team ( $args = '' ) {
global $woothemes_our_team;
return $woothemes_our_team->get_our_team( $args );
} // End woothemes_get_our_team()
}
/**
* Enable the usage of do_action( 'woothemes_our_team' ) to display team members within a theme/plugin.
*
* #since 1.0.0
*/
add_action( 'woothemes_our_team', 'woothemes_our_team' );
if ( ! function_exists( 'woothemes_our_team' ) ) {
/**
* Display or return HTML-formatted team members.
* #param string/array $args Arguments.
* #since 1.0.0
* #return string
*/
function woothemes_our_team ( $args = '' ) {
global $post, $more;
$defaults = apply_filters( 'woothemes_our_team_default_args', array(
'limit' => 12,
'per_row' => null,
'orderby' => 'menu_order',
'order' => 'DESC',
'id' => 0,
'slug' => null,
'display_author' => true,
'display_additional' => true,
'display_avatar' => true,
'display_url' => true,
'display_twitter' => true,
'display_author_archive' => true,
'display_role' => true,
'contact_email' => true,
'tel' => true,
'effect' => 'fade', // Options: 'fade', 'none'
'pagination' => false,
'echo' => true,
'size' => 250,
'title' => '',
'before' => '<div class="widget widget_woothemes_our_team">',
'after' => '</div>',
'before_title' => '<h2>',
'after_title' => '</h2>',
'category' => 0
) );
$args = wp_parse_args( $args, $defaults );
// Allow child themes/plugins to filter here.
$args = apply_filters( 'woothemes_our_team_args', $args );
$html = '';
do_action( 'woothemes_our_team_before', $args );
// The Query.
$query = woothemes_get_our_team( $args );
// The Display.
if ( ! is_wp_error( $query ) && is_array( $query ) && count( $query ) > 0 ) {
$class = '';
if ( is_numeric( $args['per_row'] ) ) {
$class .= ' columns-' . intval( $args['per_row'] );
}
if ( 'none' != $args['effect'] ) {
$class .= ' effect-' . $args['effect'];
}
$html .= $args['before'] . "\n";
if ( '' != $args['title'] ) {
$html .= html_entity_decode( $args['before_title'] ) . esc_html( $args['title'] ) . html_entity_decode( $args['after_title'] ) . "\n"; }
$html .= '<div class="team-members component' . esc_attr( $class ) . '">' . "\n";
// Begin templating logic.
$tpl = '<div itemscope itemtype="http://schema.org/Person" class="%%CLASS%%">%%AVATAR%% %%TITLE%% <div id="team-member-%%ID%%" class="team-member-text" itemprop="description">%%TEXT%% %%AUTHOR%%</div></div>';
$tpl = apply_filters( 'woothemes_our_team_item_template', $tpl, $args );
$count = 0;
foreach ( $query as $post ) {
$count++;
$template = $tpl;
$css_class = apply_filters( 'woothemes_our_team_member_class', $css_class = 'team-member' );
if ( ( is_numeric( $args['per_row'] ) && ( 0 == ( $count - 1 ) % $args['per_row'] ) ) || 1 == $count ) { $css_class .= ' first'; }
if ( ( is_numeric( $args['per_row'] ) && ( 0 == $count % $args['per_row'] ) ) ) { $css_class .= ' last'; }
// Add a CSS class if no image is available.
if ( isset( $post->image ) && ( '' == $post->image ) ) {
$css_class .= ' no-image';
}
setup_postdata( $post );
$title = '';
$title_name = '';
// If we need to display the title, get the data
if ( ( get_the_title( $post ) != '' ) && true == $args['display_author'] ) {
$title .= '<h3 itemprop="name" class="member">';
if ( true == $args['display_url'] && '' != $post->url && apply_filters( 'woothemes_our_team_member_url', true ) ) {
$title .= '<a href="' . esc_url( $post->url ) . '">' . "\n";
}
$title_name = get_the_title( $post );
$title .= $title_name;
if ( true == $args['display_url'] && '' != $post->url && apply_filters( 'woothemes_our_team_member_url', true ) ) {
$title .= '</a>' . "\n";
}
$title .= '</h3><!--/.member-->' . "\n";
$member_role = '';
if ( true == $args['display_role'] && isset( $post->byline ) && '' != $post->byline && apply_filters( 'woothemes_our_team_member_role', true ) ) {
$member_role .= ' <p class="role" itemprop="jobTitle">' . $post->byline . '</p><!--/.excerpt-->' . "\n";
}
$title .= apply_filters( 'woothemes_our_team_member_fields_display', $member_role );
}
// Templating engine replacement.
$template = str_replace( '%%TITLE%%', $title, $template );
$author = '';
$author_text = '';
$user = $post->user_id;
// If we need to display the author, get the data.
if ( true == $args['display_additional'] ) {
$author .= '<ul class="author-details">';
$member_fields = '';
if ( true == $args['display_author_archive'] && apply_filters( 'woothemes_our_team_member_user_id', true ) ) {
// User didn't select an item from the autocomplete list
// Let's try to get the user from the search query
if ( 0 == $post->user_id && '' != $post->user_search ) {
$user = get_user_by( 'slug', $post->user_search );
if ( $user ) {
$user = $user->ID;
}
}
if ( 0 != $user ) {
$member_fields .= '<li class="our-team-author-archive" itemprop="url">' . sprintf( __( 'Read posts by %1$s', 'our-team-by-woothemes' ), get_the_title() ) . '</li>' . "\n";
}
}
if ( true == $args['contact_email'] && '' != $post->contact_email && apply_filters( 'woothemes_our_team_member_contact_email', true ) ) {
$member_fields .= '<li class="our-team-contact-email" itemprop="email">' . __( 'Email me ', 'our-team-by-woothemes' ) . '</li>';
}
if ( true == $args['tel'] && '' != $post->tel && apply_filters( 'woothemes_our_team_member_tel', true ) ) {
$call_protocol = apply_filters( 'woothemes_our_team_call_protocol', $protocol = 'tel' );
$member_fields .= '<li class="our-team-tel" itemprop="telephone"><span>' . __( 'Tel: ', 'our-team-by-woothemes' ) . '</span>' . esc_html( $post->tel ) . '</li>';
}
if ( true == $args['display_twitter'] && '' != $post->twitter && apply_filters( 'woothemes_our_team_member_twitter', true ) ) {
$member_fields .= '<li class="our-team-twitter" itemprop="contactPoint">Follow #' . esc_html( $post->twitter ) . '<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?"http":"https";if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document, "script", "twitter-wjs");</script></li>' . "\n";
}
$author .= apply_filters( 'woothemes_our_member_fields_display', $member_fields );
$author .= '</ul>';
// Templating engine replacement.
$template = str_replace( '%%AUTHOR%%', $author, $template );
} else {
$template = str_replace( '%%AUTHOR%%', '', $template );
}
// Templating logic replacement.
$template = str_replace( '%%ID%%', get_the_ID(), $template );
$template = str_replace( '%%CLASS%%', esc_attr( $css_class ), $template );
if ( isset( $post->image ) && ( '' != $post->image ) && true == $args['display_avatar'] ) {
$template = str_replace( '%%AVATAR%%', '<figure itemprop="image">' . $post->image . '</figure>', $template );
} else {
$template = str_replace( '%%AVATAR%%', '', $template );
}
// Remove any remaining %%AVATAR%% template tags.
$template = str_replace( '%%AVATAR%%', '', $template );
$real_more = $more;
$more = 0;
$content = apply_filters( 'woothemes_our_team_content', wpautop( get_the_content( __( 'Read full biography...', 'our-team-by-woothemes' ) ) ), $post );
$more = $real_more;
// Display bio if Team Member is mapped to a user on this site.
if ( apply_filters( 'woothemes_our_team_display_bio', true ) && 0 != $user ) {
if ( '' != get_the_author_meta( 'description', $user ) ) {
$content = wpautop( get_the_author_meta( 'description', $user ) );
}
}
$template = str_replace( '%%TEXT%%', $content, $template );
// filter the individual team member html
$template = apply_filters( 'woothemes_our_team_member_html', $template, $post );
// Assign for output.
$html .= $template;
}
wp_reset_postdata();
if ( $args['pagination'] == true && count( $query ) > 1 && $args['effect'] != 'none' ) {
$html .= '<div class="pagination">' . "\n";
$html .= '' . apply_filters( 'woothemes_our_team_prev_btn', '← ' . __( 'Previous', 'our-team-by-woothemes' ) ) . '' . "\n";
$html .= '' . apply_filters( 'woothemes_our_team_next_btn', __( 'Next', 'our-team-by-woothemes' ) . ' →' ) . '' . "\n";
$html .= '</div><!--/.pagination-->' . "\n";
}
$html .= '</div><!--/.team-members-->' . "\n";
$html .= $args['after'] . "\n";
}
// Allow child themes/plugins to filter here.
$html = apply_filters( 'woothemes_our_team_html', $html, $query, $args );
if ( $args['echo'] != true ) {
return $html;
}
// Should only run is "echo" is set to true.
echo $html;
do_action( 'woothemes_our_team_after', $args ); // Only if "echo" is set to true.
} // End woothemes_our_team()
}
if ( ! function_exists( 'woothemes_our_team_shortcode' ) ) {
/**
* The shortcode function.
* #since 1.0.0
* #param array $atts Shortcode attributes.
* #param string $content If the shortcode is a wrapper, this is the content being wrapped.
* #return string Output using the template tag.
*/
function woothemes_our_team_shortcode ( $atts, $content = null ) {
$args = (array)$atts;
$defaults = array(
'limit' => 12,
'per_row' => null,
'orderby' => 'menu_order',
'order' => 'DESC',
'id' => 0,
'slug' => null,
'display_author' => true,
'display_additional' => true,
'display_avatar' => true,
'display_url' => true,
'display_author_archive' => true,
'display_twitter' => true,
'display_role' => true,
'effect' => 'fade', // Options: 'fade', 'none'
'pagination' => false,
'echo' => true,
'size' => 250,
'category' => 0,
'title' => '',
'before_title' => '<h2>',
'after_title' => '</h2>'
);
$args = shortcode_atts( $defaults, $atts );
// Make sure we return and don't echo.
$args['echo'] = false;
// Fix integers.
if ( isset( $args['limit'] ) ) {
$args['limit'] = intval( $args['limit'] );
}
if ( isset( $args['size'] ) && ( 0 < intval( $args['size'] ) ) ) {
$args['size'] = intval( $args['size'] );
}
if ( isset( $args['category'] ) && is_numeric( $args['category'] ) ) {
$args['category'] = intval( $args['category'] );
}
// Fix booleans.
foreach ( array( 'display_author', 'display_additional', 'display_url', 'display_author_archive', 'display_twitter', 'display_role', 'pagination', 'display_avatar' ) as $k => $v ) {
if ( isset( $args[$v] ) && ( 'true' == $args[$v] ) ) {
$args[$v] = true;
} else {
$args[$v] = false;
}
}
return woothemes_our_team( $args );
} // End woothemes_our_team_shortcode()
}
add_shortcode( 'woothemes_our_team', 'woothemes_our_team_shortcode' );
if ( ! function_exists( 'woothemes_our_team_content_default_filters' ) ) {
/**
* Adds default filters to the "woothemes_our_team_content" filter point.
* #since 1.0.0
* #return void
*/
function woothemes_our_team_content_default_filters () {
add_filter( 'woothemes_our_team_content', 'do_shortcode' );
} // End woothemes_our_team_content_default_filters()
add_action( 'woothemes_our_team_before', 'woothemes_our_team_content_default_filters' );
}
add_filter( 'the_content', 'woothemes_our_team_content' );
/**
* Display team member data on single / archive pages
* #since 1.4.0
* #return $content the post content
*/
function woothemes_our_team_content( $content ) {
global $post;
$team_member_email = esc_attr( get_post_meta( $post->ID, '_gravatar_email', true ) );
$user = esc_attr( get_post_meta( $post->ID, '_user_id', true ) );
$user_search = esc_attr( get_post_meta( $post->ID, '_user_search', true ) );
$twitter = esc_attr( get_post_meta( $post->ID, '_twitter', true ) );
$role = esc_attr( get_post_meta( $post->ID, '_byline', true ) );
$url = esc_attr( get_post_meta( $post->ID, '_url', true ) );
$tel = esc_attr( get_post_meta( $post->ID, '_tel', true ) );
$contact_email = esc_attr( get_post_meta( $post->ID, '_contact_email', true ) );
if ( 'team-member' == get_post_type() ) {
$team_member_gravatar = '';
$team_member_role = '';
$member_fields = '';
$author = '';
if ( isset( $team_member_email ) && ( '' != $team_member_email ) ) {
$team_member_gravatar = '<figure itemprop="image">' . get_avatar( $team_member_email, 250 ) . '</figure>';
}
if ( isset( $role ) && '' != $role && apply_filters( 'woothemes_our_team_member_role', true ) ) {
$team_member_role .= ' <p class="role" itemprop="jobTitle">' . $role . '</p>' . "\n";
}
$author .= '<ul class="author-details">';
if ( apply_filters( 'woothemes_our_team_member_user_id', true ) ) {
if ( 0 == $user && '' != $user_search ) {
$user = get_user_by( 'slug', $user_search );
if ( $user ) {
$user = $user;
}
}
if ( 0 != $user ) {
$member_fields .= '<li class="our-team-author-archive" itemprop="url">' . sprintf( __( 'Read posts by %1$s', 'woothemes' ), get_the_title() ) . '</li>' . "\n";
}
}
if ( '' != $tel && apply_filters( 'woothemes_our_team_member_contact_email', true ) ) {
$member_fields .= '<li class="our-team-contact-email" itemprop="email">' . __( 'Email ', 'our-team-by-woothemes' ) . get_the_title() . '</li>';
}
if ( '' != $tel && apply_filters( 'woothemes_our_team_member_tel', true ) ) {
$call_protocol = apply_filters( 'woothemes_our_team_call_protocol', $protocol = 'tel' );
$member_fields .= '<li class="our-team-tel" itemprop="telephone"><span>' . __( 'Tel: ', 'our-team-by-woothemes' ) . '</span>' . $tel . '</li>';
}
if ( '' != $twitter && apply_filters( 'woothemes_our_team_member_twitter', true ) ) {
$member_fields .= '<li class="our-team-twitter" itemprop="contactPoint">Follow #' . esc_html( $twitter ) . '<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?"http":"https";if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document, "script", "twitter-wjs");</script></li>' . "\n";
}
$author .= apply_filters( 'woothemes_our_member_fields_display', $member_fields );
$author .= '</ul>';
return $team_member_gravatar . $team_member_role . $content . $author;
} else {
return $content;
}
}
You can filter the template:
function so_27863277_our_team_template( $tpl, $args ){
$tpl = '<div itemscope itemtype="http://schema.org/Person" class="%%CLASS%%">%%AVATAR%% %%TITLE%% Read About Me<div id="team-member-%%ID%%" class="team-member-text" itemprop="description">%%TEXT%% %%AUTHOR%%</div></div>';
return $tpl;
}
add_filter( 'woothemes_our_team_item_template', 'so_27863277_our_team_template', 10, 2 );
Then by default, you might also want to style the team-member-text div so that it is hidden.
.team-member-text{ display: none; }
I'm not sure how to make it work with your particular lightbox plugin so you will have to adapt that part yourself.
i have a shortcode that posts recent blog entries from a certain category on one of my web pages, however i want to display a static link at the end of everypost, is there anyway to do this?
the following code is used to display the posts:
<?php echo do_shortcode('[display-posts category="competitions" posts_per_page="4" include_excerpt="true" image_size="thumbnail" wrapper="ul"]');
Thanks in advance.
<?php
// Create the shortcode
add_shortcode( 'display-posts', 'be_display_posts_shortcode' );
function be_display_posts_shortcode( $atts ) {
// Original Attributes, for filters
$original_atts = $atts;
// Pull in shortcode attributes and set defaults
$atts = shortcode_atts( array(
'title' => '',
'author' => '',
'category' => '',
'date_format' => '(n/j/Y)',
'display_posts_off' => false,
'exclude_current' => false,
'id' => false,
'ignore_sticky_posts' => false,
'image_size' => false,
'include_title' => true,
'include_author' => false,
'include_content' => false,
'include_date' => false,
'include_excerpt' => false,
'meta_key' => '',
'meta_value' => '',
'no_posts_message' => '',
'offset' => 0,
'order' => 'DESC',
'orderby' => 'date',
'post_parent' => false,
'post_status' => 'publish',
'post_type' => 'post',
'posts_per_page' => '10',
'tag' => '',
'tax_operator' => 'IN',
'tax_term' => false,
'taxonomy' => false,
'wrapper' => 'ul',
'wrapper_class' => 'display-posts-listing',
'wrapper_id' => false,
), $atts, 'display-posts' );
// End early if shortcode should be turned off
if( $atts['display_posts_off'] )
return;
$shortcode_title = sanitize_text_field( $atts['title'] );
$author = sanitize_text_field( $atts['author'] );
$category = sanitize_text_field( $atts['category'] );
$date_format = sanitize_text_field( $atts['date_format'] );
$exclude_current = be_display_posts_bool( $atts['exclude_current'] );
$id = $atts['id']; // Sanitized later as an array of integers
$ignore_sticky_posts = be_display_posts_bool( $atts['ignore_sticky_posts'] );
$image_size = sanitize_key( $atts['image_size'] );
$include_title = be_display_posts_bool( $atts['include_title'] );
$include_author = be_display_posts_bool( $atts['include_author'] );
$include_content = be_display_posts_bool( $atts['include_content'] );
$include_date = be_display_posts_bool( $atts['include_date'] );
$include_excerpt = be_display_posts_bool( $atts['include_excerpt'] );
$meta_key = sanitize_text_field( $atts['meta_key'] );
$meta_value = sanitize_text_field( $atts['meta_value'] );
$no_posts_message = sanitize_text_field( $atts['no_posts_message'] );
$offset = intval( $atts['offset'] );
$order = sanitize_key( $atts['order'] );
$orderby = sanitize_key( $atts['orderby'] );
$post_parent = $atts['post_parent']; // Validated later, after check for 'current'
$post_status = $atts['post_status']; // Validated later as one of a few values
$post_type = sanitize_text_field( $atts['post_type'] );
$posts_per_page = intval( $atts['posts_per_page'] );
$tag = sanitize_text_field( $atts['tag'] );
$tax_operator = $atts['tax_operator']; // Validated later as one of a few values
$tax_term = sanitize_text_field( $atts['tax_term'] );
$taxonomy = sanitize_key( $atts['taxonomy'] );
$wrapper = sanitize_text_field( $atts['wrapper'] );
$wrapper_class = sanitize_html_class( $atts['wrapper_class'] );
if( !empty( $wrapper_class ) )
$wrapper_class = ' class="' . $wrapper_class . '"';
$wrapper_id = sanitize_html_class( $atts['wrapper_id'] );
if( !empty( $wrapper_id ) )
$wrapper_id = ' id="' . $wrapper_id . '"';
// Set up initial query for post
$args = array(
'category_name' => $category,
'order' => $order,
'orderby' => $orderby,
'post_type' => explode( ',', $post_type ),
'posts_per_page' => $posts_per_page,
'tag' => $tag,
);
// Ignore Sticky Posts
if( $ignore_sticky_posts )
$args['ignore_sticky_posts'] = true;
// Meta key (for ordering)
if( !empty( $meta_key ) )
$args['meta_key'] = $meta_key;
// Meta value (for simple meta queries)
if( !empty( $meta_value ) )
$args['meta_value'] = $meta_value;
// If Post IDs
if( $id ) {
$posts_in = array_map( 'intval', explode( ',', $id ) );
$args['post__in'] = $posts_in;
}
// If Exclude Current
if( $exclude_current )
$args['post__not_in'] = array( get_the_ID() );
// Post Author
if( !empty( $author ) )
$args['author_name'] = $author;
// Offset
if( !empty( $offset ) )
$args['offset'] = $offset;
// Post Status
$post_status = explode( ', ', $post_status );
$validated = array();
$available = array( 'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', 'trash', 'any' );
foreach ( $post_status as $unvalidated )
if ( in_array( $unvalidated, $available ) )
$validated[] = $unvalidated;
if( !empty( $validated ) )
$args['post_status'] = $validated;
// If taxonomy attributes, create a taxonomy query
if ( !empty( $taxonomy ) && !empty( $tax_term ) ) {
// Term string to array
$tax_term = explode( ', ', $tax_term );
// Validate operator
if( !in_array( $tax_operator, array( 'IN', 'NOT IN', 'AND' ) ) )
$tax_operator = 'IN';
$tax_args = array(
'tax_query' => array(
array(
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $tax_term,
'operator' => $tax_operator
)
)
);
// Check for multiple taxonomy queries
$count = 2;
$more_tax_queries = false;
while(
isset( $original_atts['taxonomy_' . $count] ) && !empty( $original_atts['taxonomy_' . $count] ) &&
isset( $original_atts['tax_' . $count . '_term'] ) && !empty( $original_atts['tax_' . $count . '_term'] )
):
// Sanitize values
$more_tax_queries = true;
$taxonomy = sanitize_key( $original_atts['taxonomy_' . $count] );
$terms = explode( ', ', sanitize_text_field( $original_atts['tax_' . $count . '_term'] ) );
$tax_operator = isset( $original_atts['tax_' . $count . '_operator'] ) ? $original_atts['tax_' . $count . '_operator'] : 'IN';
$tax_operator = in_array( $tax_operator, array( 'IN', 'NOT IN', 'AND' ) ) ? $tax_operator : 'IN';
$tax_args['tax_query'][] = array(
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $terms,
'operator' => $tax_operator
);
$count++;
endwhile;
if( $more_tax_queries ):
$tax_relation = 'AND';
if( isset( $original_atts['tax_relation'] ) && in_array( $original_atts['tax_relation'], array( 'AND', 'OR' ) ) )
$tax_relation = $original_atts['tax_relation'];
$args['tax_query']['relation'] = $tax_relation;
endif;
$args = array_merge( $args, $tax_args );
}
// If post parent attribute, set up parent
if( $post_parent ) {
if( 'current' == $post_parent ) {
global $post;
$post_parent = get_the_ID();
}
$args['post_parent'] = intval( $post_parent );
}
// Set up html elements used to wrap the posts.
// Default is ul/li, but can also be ol/li and div/div
$wrapper_options = array( 'ul', 'ol', 'div' );
if( ! in_array( $wrapper, $wrapper_options ) )
$wrapper = 'ul';
$inner_wrapper = 'div' == $wrapper ? 'div' : 'li';
$listing = new WP_Query( apply_filters( 'display_posts_shortcode_args', $args, $original_atts ) );
if ( ! $listing->have_posts() )
return apply_filters( 'display_posts_shortcode_no_results', wpautop( $no_posts_message ) );
$inner = '';
while ( $listing->have_posts() ): $listing->the_post(); global $post;
$image = $date = $author = $excerpt = $content = '';
if ( $include_title )
$title = '<a class="title" href="' . apply_filters( 'the_permalink', get_permalink() ) . '">' . get_the_title() . '</a>';
if ( $image_size && has_post_thumbnail() )
$image = '<a class="image" href="' . get_permalink() . '">' . get_the_post_thumbnail( get_the_ID(), $image_size ) . '</a> ';
if ( $include_date )
$date = ' <span class="date">' . get_the_date( $date_format ) . '</span>';
if( $include_author )
$author = apply_filters( 'display_posts_shortcode_author', ' <span class="author">by ' . get_the_author() . '</span>' );
if ( $include_excerpt )
$excerpt = ' <span class="excerpt-dash">-</span> <span class="excerpt">' . get_the_excerpt() . '</span>';
if( $include_content ) {
add_filter( 'shortcode_atts_display-posts', 'be_display_posts_off', 10, 3 );
$content = '<div class="content">' . apply_filters( 'the_content', get_the_content() ) . '</div>';
remove_filter( 'shortcode_atts_display-posts', 'be_display_posts_off', 10, 3 );
}
$class = array( 'listing-item' );
$class = sanitize_html_class( apply_filters( 'display_posts_shortcode_post_class', $class, $post, $listing, $original_atts ) );
$output = '<' . $inner_wrapper . ' class="' . implode( ' ', $class ) . '">' . $image . $title . $date . $author . $excerpt . $content . '</' . $inner_wrapper . '>';
// If post is set to private, only show to logged in users
if( 'private' == get_post_status( get_the_ID() ) && !current_user_can( 'read_private_posts' ) )
$output = '';
$inner .= apply_filters( 'display_posts_shortcode_output', $output, $original_atts, $image, $title, $date, $excerpt, $inner_wrapper, $content, $class );
endwhile; wp_reset_postdata();
$open = apply_filters( 'display_posts_shortcode_wrapper_open', '<' . $wrapper . $wrapper_class . $wrapper_id . '>', $original_atts );
$close = apply_filters( 'display_posts_shortcode_wrapper_close', '</' . $wrapper . '>', $original_atts );
$return = $open;
if( $shortcode_title ) {
$title_tag = apply_filters( 'display_posts_shortcode_title_tag', 'h2', $original_atts );
$return .= '<' . $title_tag . ' class="display-posts-title">' . $shortcode_title . '</' . $title_tag . '>' . "\n";
}
$return .= $inner . $close;
return $return;
}
/**
* Turn off display posts shortcode
* If display full post content, any uses of [display-posts] are disabled
*
* #param array $out, returned shortcode values
* #param array $pairs, list of supported attributes and their defaults
* #param array $atts, original shortcode attributes
* #return array $out
*/
function be_display_posts_off( $out, $pairs, $atts ) {
$out['display_posts_off'] = true;
return $out;
}
/**
* Convert string to boolean
* because (bool) "false" == true
*
*/
function be_display_posts_bool( $value ) {
return !empty( $value ) && 'true' == $value ? true : false;
}
You'll want to edit you $output variable which is on line 243 on the code you've given above.
A simple amendment to add a static url will do fine, something like this:
$static_link = 'http://www.test.com/test';
$output = '<' . $inner_wrapper . ' class="' . implode( ' ', $class ) . '">' . $image . $title . $date . $author . $excerpt . $content . 'Read more' . '</' . $inner_wrapper . '>';
Amend this to your requirements, say adding a proper link from the database.
Hope this helps.