In my wordpress theme I am creating some custom fields like
cp_street, cp_city, cp_mobile_no, cp_company_name
and much more. Which is displayed in single_ad_listing.php page, and code is
cp_get_ad_details( $post->ID, $cat_id );
and theme-function.php page code is
// display all the custom fields on the single ad page, by default they are placed in the list area
if ( ! function_exists('cp_get_ad_details') ) {
function cp_get_ad_details( $post_id, $category_id, $location = 'list' ) {
global $wpdb;
// see if there's a custom form first based on category id.
$form_id = cp_get_form_id( $category_id );
$post = get_post( $post_id );
if ( ! $post )
return;
// if there's no form id it must mean the default form is being used
if ( ! $form_id ) {
// get all the custom field labels so we can match the field_name up against the post_meta keys
$sql = "SELECT field_label, field_name, field_type FROM $wpdb->cp_ad_fields";
} else {
// now we should have the formid so show the form layout based on the category selected
$sql = $wpdb->prepare( "SELECT f.field_label, f.field_name, f.field_type, m.field_pos FROM $wpdb->cp_ad_fields f "
. "INNER JOIN $wpdb->cp_ad_meta m ON f.field_id = m.field_id WHERE m.form_id = %s ORDER BY m.field_pos ASC", $form_id );
}
$results = $wpdb->get_results( $sql );
if ( ! $results ) {
_e( 'No ad details found.', APP_TD );
return;
}
// allows to hook before ad details
cp_action_before_ad_details( $results, $post, $location );
foreach ( $results as $result ) {
// external plugins can modify or disable field
$result = apply_filters( 'cp_ad_details_field', $result, $post, $location );
if ( ! $result )
continue;
$disallow_fields = array( 'cp_price', 'cp_currency' );
if ( in_array( $result->field_name, $disallow_fields ) )
continue;
$post_meta_val = get_post_meta( $post->ID, $result->field_name, true );
if ( empty( $post_meta_val ) )
continue;
if ( $location == 'list' ) {
if ( $result->field_type == 'text area' )
continue;
if ( $result->field_type == 'checkbox' ) {
$post_meta_val = get_post_meta( $post->ID, $result->field_name, false );
$post_meta_val = implode( ", ", $post_meta_val );
}
$args = array( 'value' => $post_meta_val, 'label' => $result->field_label, 'id' => $result->field_name, 'class' => '' );
$args = apply_filters( 'cp_ad_details_' . $result->field_name, $args, $result, $post, $location );
if ( $args )
echo '<li id="' . $args['id'] . '" class="' . $args['class'] . '"><span>' . esc_html( translate( $args['label'], APP_TD ) ) . ':</span> ' . appthemes_make_clickable( $args['value'] ) . '</li>';
} elseif ( $location == 'content' ) {
if ( $result->field_type != 'text area' )
continue;
$args = array( 'value' => $post_meta_val, 'label' => $result->field_label, 'id' => $result->field_name, 'class' => 'custom-text-area dotted' );
$args = apply_filters( 'cp_ad_details_' . $result->field_name, $args, $result, $post, $location );
if ( $args )
echo '<div id="' . $args['id'] . '" class="' . $args['class'] . '"><h3>' . esc_html( translate( $args['label'], APP_TD ) ) . '</h3> ' . appthemes_make_clickable( $args['value'] ) . '</div>';
}
}
All fields display serially, but I want to like address cp_street, cp_city top of page and mobile no.( cp_mobile_no) right side of page and rest of fields display same place.
Please help me...
In this tutorial we will look at how the Advanced Custom Fields plugin can be used to create a professional home page .
i hope this like use full.. here simple code..
Related
I added successfully a Metabox with a multi checkbox field that is displayed on admin single order pages and works perfectly.
I am using Multi checkbox fields in Woocommerce backend answer code for that multi checkbox.
// Adding Meta container admin shop_order pages
add_action( 'add_meta_boxes', 'em_add_meta_boxes' );
if ( ! function_exists( 'em_add_meta_boxes' ) )
{
function em_add_meta_boxes()
{
add_meta_box( 'em_other_fields', __('Employee Extra Actions','woocommerce'), 'em_add_other_fields_for_order_empl', 'shop_order', 'side', 'core' );
}
}
// Adding Meta field in the meta container admin shop_order pages
if ( ! function_exists( 'em_add_other_fields_for_order_empl' ) )
{
function em_add_other_fields_for_order_empl()
{
global $post;
echo '<div class="options_group">';
woocommerce_wp_multi_checkbox( array(
'id' => 'employee_actions12',
'name' => 'employee_actions12[]',
'label' => __('Levels', 'woocommerce'),
'options' => array(
'tee' => __( 'MBO', 'woocommerce' ),
'saa' => __( 'HBO', 'woocommerce' ),
'tee1' => __( 'WO', 'woocommerce' ),
)
) );
echo '</div>';
}
}
Final part of code is to save at database, Here is it:
add_action( 'save_post', 'save_product_options_custom_fields32', 30, 1 );
function save_product_options_custom_fields32( $post_id ){
if( isset( $_POST['employee_actions12'] ) ){
$post_data = $_POST['employee_actions12'];
// Multi data sanitization
$sanitize_data = array();
if( is_array($post_data) && sizeof($post_data) > 0 ){
foreach( $post_data as $value ){
$sanitize_data[] = esc_attr( $value );
}
}
update_post_meta( $post_id, 'employee_actions12', $sanitize_data );
}
}
I know code works for product pages with action: 'woocommerce_product_process_meta'
So, i need help for saving at db, an fixing error notice for array (i think this can happen if we select default value).
There was another issue with the function woocommerce_wp_multi_checkbox() that I have updated again (when used in a custom metabox).
I have also revisited all your code, specially the last function that saves the multi-checkboxes selected values.
The complete code:
// WooCommerce admin custom multi checkbox field function
function woocommerce_wp_multi_checkbox( $field ) {
global $thepostid, $post;
if( ! $thepostid ) {
$thepostid = $post->ID;
}
$field['value'] = get_post_meta( $thepostid, $field['id'], true );
$thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
$field['class'] = isset( $field['class'] ) ? $field['class'] : 'select short';
$field['style'] = isset( $field['style'] ) ? $field['style'] : '';
$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
$field['value'] = isset( $field['value'] ) ? $field['value'] : array();
$field['name'] = isset( $field['name'] ) ? $field['name'] : $field['id'];
$field['desc_tip'] = isset( $field['desc_tip'] ) ? $field['desc_tip'] : false;
echo '<fieldset class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '">
<legend>' . wp_kses_post( $field['label'] ) . '</legend>';
if ( ! empty( $field['description'] ) && false !== $field['desc_tip'] ) {
echo wc_help_tip( $field['description'] );
}
echo '<ul class="wc-radios">';
foreach ( $field['options'] as $key => $value ) {
echo '<li><label><input
name="' . esc_attr( $field['name'] ) . '"
value="' . esc_attr( $key ) . '"
type="checkbox"
class="' . esc_attr( $field['class'] ) . '"
style="' . esc_attr( $field['style'] ) . '"
' . ( is_array( $field['value'] ) && in_array( $key, $field['value'] ) ? 'checked="checked"' : '' ) . ' /> ' . esc_html( $value ) . '</label>
</li>';
}
echo '</ul>';
if ( ! empty( $field['description'] ) && false === $field['desc_tip'] ) {
echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
}
echo '</fieldset>';
}
// Adding a custom Metabox on WooCommerce single orders
add_action( 'add_meta_boxes', 'add_custom_shop_order_metabox' );
function add_custom_shop_order_metabox(){
add_meta_box(
'custom_shop_order_metabox',
__('Employee Extra Actions', 'woocommerce'),
'content_custom_shop_order_metabox',
'shop_order',
'side',
'core'
);
}
// Custom Metabox content on WooCommerce single orders
function content_custom_shop_order_metabox() {
global $thepostid, $post;
echo '<div class="options_group">';
woocommerce_wp_multi_checkbox( array(
'id' => 'employee_actions12',
'name' => 'employee_actions12[]',
'label' => __('Levels', 'woocommerce'),
'options' => array(
'tee' => __( 'MBO', 'woocommerce' ),
'saa' => __( 'HBO', 'woocommerce' ),
'tee1' => __( 'WO', 'woocommerce' ),
),
) );
echo '</div>';
}
// Save WooCommerce single orders Custom Metabox field values
add_action( 'save_post_shop_order', 'save_custom_shop_order_metabox_field_values' );
function save_custom_shop_order_metabox_field_values( $post_id ){
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
|| ! current_user_can( 'edit_shop_order', $post_id ) ) {
return;
}
if( isset( $_POST['employee_actions12'] ) ){
update_post_meta( $post_id, 'employee_actions12', wc_clean($_POST['employee_actions12']) );
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
There is a widget called Active Product Filter in WooCommerce, I couldn't find a way to override it's designed so I tried making my own;
function abc_active_filter(){
$queryData = array();
parse_str($_SERVER['QUERY_STRING'], $queryData);
$active_filter = '';
foreach($queryData as $key => $value){
$active_filter = $active_filter.'<div>CLIK TO REMOVE - <span>'.$key.'</span><div>';
}
if(sizeof($queryData) > 0){
$active_filter = '<h3>Active Filter</h3>'.$active_filter;
}
return $active_filter;
}
add_shortcode('csx_active_filter', 'abc_active_filter');
This will output the query key of the current URL, for example;
min_price,
filter_size
whereas using the widget Active Product Filter the output is;
Min Price $589
Large
is there a way to achieve the output the same as the Active Product Filter? I found this the same question with me but the accepted answer is far different from what I'm trying to achieve and the one who asked the question is only looking for active filters by checking the query key.
Anyway, with the following code, I can achieve the same output of Active Product Filter;
if($key === 'min_price'){
$active_filter = $active_filter.'<div>CLIK TO REMOVE - <span>Min Price '.$value.'</span><div>';
}else if($key === 'filter_size'){
$active_filter = $active_filter.'<div>CLIK TO REMOVE - <span>'.$value.'</span><div>';
}else if .... and so on...
The problem is, filters are dynamic and I don't know all of them and it will take a lot of lines of codes to put them in conditional statements.
You can try using WC_Query::get_layered_nav_chosen_attributes();, simply print its value and see if the result is what you need.
print_r(WC_Query::get_layered_nav_chosen_attributes());
Otherwise, I wouldn't recommend to reinvent the wheel. You can override the widget by extending the class of WC_Widget_Layered_Nav_Filters.
In your functions.php, insert the below code. You can change its layout, elements depending on what design you wanted.
class Your_New_WC_Widget_Layered_Nav_Filters extends WC_Widget_Layered_Nav_Filters {
/**
* Constructor.
*/
public function __construct() {
$this->widget_cssclass = 'woocommerce widget_layered_nav_filters';
$this->widget_description = __( 'Display a list of active product filters.', 'woocommerce' );
$this->widget_id = 'woocommerce_layered_nav_filters';
$this->widget_name = __( 'Active Product Filters', 'woocommerce' );
$this->settings = array(
'title' => array(
'type' => 'text',
'std' => __( 'The Active filters', 'woocommerce' ),
'label' => __( 'Title', 'woocommerce' ),
),
);
parent::__construct();
}
/**
* Output widget.
*
* #see WP_Widget
* #param array $args Arguments.
* #param array $instance Widget instance.
*/
public function widget( $args, $instance ) {
if ( ! is_shop() && ! is_product_taxonomy() ) {
return;
}
$_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes();
$min_price = isset( $_GET['min_price'] ) ? wc_clean( wp_unslash( $_GET['min_price'] ) ) : 0; // WPCS: input var ok, CSRF ok.
$max_price = isset( $_GET['max_price'] ) ? wc_clean( wp_unslash( $_GET['max_price'] ) ) : 0; // WPCS: input var ok, CSRF ok.
$rating_filter = isset( $_GET['rating_filter'] ) ? array_filter( array_map( 'absint', explode( ',', wp_unslash( $_GET['rating_filter'] ) ) ) ) : array(); // WPCS: sanitization ok, input var ok, CSRF ok.
$base_link = $this->get_current_page_url();
if ( 0 < count( $_chosen_attributes ) || 0 < $min_price || 0 < $max_price || ! empty( $rating_filter ) ) {
$this->widget_start( $args, $instance );
echo '<ul>';
// Attributes.
if ( ! empty( $_chosen_attributes ) ) {
foreach ( $_chosen_attributes as $taxonomy => $data ) {
foreach ( $data['terms'] as $term_slug ) {
$term = get_term_by( 'slug', $term_slug, $taxonomy );
if ( ! $term ) {
continue;
}
$filter_name = 'filter_' . wc_attribute_taxonomy_slug( $taxonomy );
$current_filter = isset( $_GET[ $filter_name ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ $filter_name ] ) ) ) : array(); // WPCS: input var ok, CSRF ok.
$current_filter = array_map( 'sanitize_title', $current_filter );
$new_filter = array_diff( $current_filter, array( $term_slug ) );
$link = remove_query_arg( array( 'add-to-cart', $filter_name ), $base_link );
if ( count( $new_filter ) > 0 ) {
$link = add_query_arg( $filter_name, implode( ',', $new_filter ), $link );
}
echo '<li class="chosen"><a rel="nofollow" aria-label="' . esc_attr__( 'Remove filter', 'woocommerce' ) . '" href="' . esc_url( $link ) . '">' . esc_html( $term->name ) . '</a></li>';
}
}
}
if ( $min_price ) {
$link = remove_query_arg( 'min_price', $base_link );
/* translators: %s: minimum price */
echo '<li class="chosen"><a rel="nofollow" aria-label="' . esc_attr__( 'Remove filter', 'woocommerce' ) . '" href="' . esc_url( $link ) . '">' . sprintf( __( 'Min %s', 'woocommerce' ), wc_price( $min_price ) ) . '</a></li>'; // WPCS: XSS ok.
}
if ( $max_price ) {
$link = remove_query_arg( 'max_price', $base_link );
/* translators: %s: maximum price */
echo '<li class="chosen"><a rel="nofollow" aria-label="' . esc_attr__( 'Remove filter', 'woocommerce' ) . '" href="' . esc_url( $link ) . '">' . sprintf( __( 'Max %s', 'woocommerce' ), wc_price( $max_price ) ) . '</a></li>'; // WPCS: XSS ok.
}
if ( ! empty( $rating_filter ) ) {
foreach ( $rating_filter as $rating ) {
$link_ratings = implode( ',', array_diff( $rating_filter, array( $rating ) ) );
$link = $link_ratings ? add_query_arg( 'rating_filter', $link_ratings ) : remove_query_arg( 'rating_filter', $base_link );
/* translators: %s: rating */
echo '<li class="chosen"><a rel="nofollow" aria-label="' . esc_attr__( 'Remove filter', 'woocommerce' ) . '" href="' . esc_url( $link ) . '">' . sprintf( esc_html__( 'Rated %s out of 5', 'woocommerce' ), esc_html( $rating ) ) . '</a></li>';
}
}
echo '</ul>';
$this->widget_end( $args );
}
}
}
Now, in your functions.php, insert the below code again. This will unregister the default widget and replace with the new one above where your custom design or layout exist.
function your_function_for_overriding_widgets() {
unregister_widget( 'WC_Widget_Layered_Nav_Filters' ); //unregistered the default widget
register_widget( 'Your_New_WC_Widget_Layered_Nav_Filters' ); //register your new widget
}
add_action( 'widgets_init', 'your_function_for_overriding_widgets' );
I want to change a given menu with submenus into a dropdown menu.
Actually it opens a new row below the main menu. You can see in the given screenshot here.
I have searched in the code for the shown css class nm-shop-sub-categories and found this function. The class nm-shop-sub-categories is at the end of the function.
/*
* Product category menu: Output
*/
if ( ! function_exists( 'nm_category_menu_output' ) ) {
function nm_category_menu_output( $is_category, $current_cat_id, $hide_empty ) {
global $wp_query, $nm_theme_options;
$page_id = wc_get_page_id( 'shop' );
$page_url = get_permalink( $page_id );
$hide_sub = true;
$current_top_cat_id = null;
$all_categories_class = '';
// Is this a category page?
if ( $is_category ) {
$hide_sub = false;
// Get current category's top-parent id
$current_cat_parents = get_ancestors( $current_cat_id, 'product_cat' );
if ( ! empty( $current_cat_parents ) ) {
$current_top_cat_id = end( $current_cat_parents ); // Get last item from array
}
// Get current category's direct children
$current_cat_direct_children = get_terms( 'product_cat',
array(
'fields' => 'ids',
'parent' => $current_cat_id,
'hierarchical' => true,
'hide_empty' => $hide_empty
)
);
$category_has_children = ( empty( $current_cat_direct_children ) ) ? false : true;
} else {
// No current category, set "All" as current (if not product tag archive or search)
if ( ! is_product_tag() && ! isset( $_REQUEST['s'] ) ) {
$all_categories_class = ' class="current-cat"';
}
}
$output_cat = '<li' . $all_categories_class . '>' . esc_html__( 'All', 'nm-framework' ) . '</li>';
$output_sub_cat = '';
$output_current_sub_cat = '';
// Categories order
$orderby = 'slug';
$order = 'asc';
if ( isset( $nm_theme_options['shop_categories_orderby'] ) ) {
$orderby = $nm_theme_options['shop_categories_orderby'];
$order = $nm_theme_options['shop_categories_order'];
}
$categories = get_categories( array(
'type' => 'post',
'orderby' => $orderby, // Note: 'name' sorts by product category "menu/sort order"
'order' => $order,
'hide_empty' => $hide_empty,
'hierarchical' => 1,
'taxonomy' => 'product_cat'
) );
// Categories menu divider
$categories_menu_divider = apply_filters( 'nm_shop_categories_divider', '<span>⁄</span>' );
foreach( $categories as $category ) {
// Is this a sub-category?
if ( $category->parent != '0' ) {
// Should sub-categories be included?
if ( $hide_sub ) {
continue; // Skip to next loop item
} else {
if (
$category->parent == $current_cat_id || // Include current sub-category's children
! $category_has_children && $category->parent == $wp_query->queried_object->parent // Include categories with the same parent (if current sub-category doesn't have children)
) {
$output_sub_cat .= nm_category_menu_create_list( $category, $current_cat_id, $categories_menu_divider );
} else if (
$category->term_id == $current_cat_id // Include current sub-category (save in a separate variable so it can be appended to the start of the category list)
) {
$output_current_sub_cat = nm_category_menu_create_list( $category, $current_cat_id, $categories_menu_divider );
}
}
} else {
$output_cat .= nm_category_menu_create_list( $category, $current_cat_id, $categories_menu_divider, $current_top_cat_id );
}
}
if ( strlen( $output_sub_cat ) > 0 ) {
$output_sub_cat = '<ul class="nm-shop-sub-categories">' . $output_current_sub_cat . $output_sub_cat . '</ul>';
}
$output = $output_cat . $output_sub_cat;
echo $output;
}
}
Is it possible to rewrite the function to generate a dropdown menu instead of the shown menu?
As you can see in the screenshot the css class
<ul class="nm-shop-sub-categories">
<li>item_1</li>
<li>item_2</li>
</ul>
is not inside the parent listing. But I want it to be like this structure:
<ul class="nm-shop-categories">
<li>parent_item_1</li>
<ul class="nm-shop-sub-categories">
<li>sub_item_1</li>
<li>sub_item_2</li>
</ul>
<li>parent_item_2</li>
</ul>
Since in my code is no classic html I don't know how to change that via php. Any ideas?
Or is there no need to change the structure and I can use css to make change this menu into a clssic dropdown menu?
Update: I've made the changes mentioned by Norman. But it didn't solved the problem. The subcategories are still seperate from the parent ul elements.
In addition to the fist block of code I've found a second one relating to subcategories. Maybe this would be of any help?
/*
* Product category menu: Output sub-categories
*/
if ( ! function_exists( 'nm_sub_category_menu_output' ) ) {
function nm_sub_category_menu_output( $current_cat_id, $hide_empty ) {
global $wp_query, $nm_theme_options;
// Categories menu divider
$categories_menu_divider = apply_filters( 'nm_shop_categories_divider', '<span>⁄</span>' );
$output_sub_categories = '';
// Categories order
$orderby = 'slug';
$order = 'asc';
if ( isset( $nm_theme_options['shop_categories_orderby'] ) ) {
$orderby = $nm_theme_options['shop_categories_orderby'];
$order = $nm_theme_options['shop_categories_order'];
}
$sub_categories = get_categories( array(
'type' => 'post',
'parent' => $current_cat_id,
'orderby' => $orderby, // Note: 'name' sorts by product category "menu/sort order"
'order' => $order,
'hide_empty' => $hide_empty,
'hierarchical' => 1,
'taxonomy' => 'product_cat'
) );
$has_sub_categories = ( empty( $sub_categories ) ) ? false : true;
// Is there any sub-categories available
if ( $has_sub_categories ) {
//$current_cat_name = __( 'All', 'nm-framework' );
$current_cat_name = apply_filters( 'nm_shop_parent_category_title', $wp_query->queried_object->name );
foreach( $sub_categories as $sub_category ) {
$output_sub_categories .= nm_category_menu_create_list( $sub_category, $current_cat_id, $categories_menu_divider );
}
} else {
$current_cat_name = $wp_query->queried_object->name;
}
// "Back" link
$output_back_link = '';
if ( $nm_theme_options['shop_categories_back_link'] ) {
$parent_cat_id = $wp_query->queried_object->parent;
if ( $parent_cat_id ) {
// Back to parent-category link
$parent_cat_url = get_term_link( (int) $parent_cat_id, 'product_cat' );
$output_back_link = nm_sub_category_menu_back_link( $parent_cat_url, $categories_menu_divider );
} else if ( $nm_theme_options['shop_categories_back_link'] == '1st' ) {
// 1st sub-level - Back to top-level (main shop page) link
$shop_page_id = wc_get_page_id( 'shop' );
$shop_url = get_permalink( $shop_page_id );
$output_back_link = nm_sub_category_menu_back_link( $shop_url, $categories_menu_divider, ' 1st-level' );
}
}
// Current category link
$current_cat_url = get_term_link( (int) $current_cat_id, 'product_cat' );
$output_current_cat = '<li class="current-cat">' . esc_html( $current_cat_name ) . '</li>';
echo $output_back_link . $output_current_cat . $output_sub_categories;
}
}
Structure you required is not the best to manage with CSS
As per the code assumption it seems like you need below structure as the resultant.
<ul class="nm-shop-categories">
<li>parent_item_1
<ul class="nm-shop-sub-categories">
<li>sub_item_1</li>
<li>sub_item_2</li>
</ul>
</li>
<li>parent_item_2</li>
</ul>
To achieve the above structure, i would suggest you to change the line this
$output_cat = '<li' . $all_categories_class . '>' . esc_html__( 'All', 'nm-framework' ) . '</li>';
To
$output_cat = '<li' . $all_categories_class . '>';
$output_cat .= '' . esc_html__( 'All', 'nm-framework' ) . '';
And End of output
$output = $output_cat . $output_sub_cat;
To
$output = $output_cat . $output_sub_cat .'</li>';
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 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.