I use woocommerce and the standard widgets are fine, but I want to add the option to show products only from a certain category. Here is the code for the standard widget:
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* List products. One widget to rule them all.
*
* #author WooThemes
* #category Widgets
* #package WooCommerce/Widgets
* #version 2.3.0
* #extends WC_Widget
*/
class WC_Widget_Products extends WC_Widget {
/**
* Constructor
*/
public function __construct() {
$this->widget_cssclass = 'woocommerce widget_products';
$this->widget_description = __( 'Display a list of your products on your site.', 'woocommerce' );
$this->widget_id = 'woocommerce_products';
$this->widget_name = __( 'WooCommerce Products', 'woocommerce' );
$this->settings = array(
'title' => array(
'type' => 'text',
'std' => __( 'Products', 'woocommerce' ),
'label' => __( 'Title', 'woocommerce' )
),
'number' => array(
'type' => 'number',
'step' => 1,
'min' => 1,
'max' => '',
'std' => 5,
'label' => __( 'Number of products to show', 'woocommerce' )
),
'show' => array(
'type' => 'select',
'std' => '',
'label' => __( 'Show', 'woocommerce' ),
'options' => array(
'' => __( 'All Products', 'woocommerce' ),
'featured' => __( 'Featured Products', 'woocommerce' ),
'onsale' => __( 'On-sale Products', 'woocommerce' ),
)
),
'orderby' => array(
'type' => 'select',
'std' => 'date',
'label' => __( 'Order by', 'woocommerce' ),
'options' => array(
'date' => __( 'Date', 'woocommerce' ),
'price' => __( 'Price', 'woocommerce' ),
'rand' => __( 'Random', 'woocommerce' ),
'sales' => __( 'Sales', 'woocommerce' ),
)
),
'order' => array(
'type' => 'select',
'std' => 'desc',
'label' => _x( 'Order', 'Sorting order', 'woocommerce' ),
'options' => array(
'asc' => __( 'ASC', 'woocommerce' ),
'desc' => __( 'DESC', 'woocommerce' ),
)
),
'in_cat' => array(
'type' => 'text',
'std' => __( 'Category Number', 'woocommerce' ),
'label' => __( 'In Category', 'woocommerce' )
),
'hide_free' => array(
'type' => 'checkbox',
'std' => 0,
'label' => __( 'Hide free products', 'woocommerce' )
),
'show_hidden' => array(
'type' => 'checkbox',
'std' => 0,
'label' => __( 'Show hidden products', 'woocommerce' )
)
);
parent::__construct();
}
/**
* Query the products and return them
* #param array $args
* #param array $instance
* #return WP_Query
*/
public function get_products( $args, $instance ) {
$number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : $this->settings['number']['std'];
$show = ! empty( $instance['show'] ) ? sanitize_title( $instance['show'] ) : $this->settings['show']['std'];
$orderby = ! empty( $instance['orderby'] ) ? sanitize_title( $instance['orderby'] ) : $this->settings['orderby']['std'];
$order = ! empty( $instance['order'] ) ? sanitize_title( $instance['order'] ) : $this->settings['order']['std'];
$cat = ! empty( $instance['in_cat'] ) ? sanitize_title( $instance['in_cat'] ) : $this->settings['in_cat']['std'];
$query_args = array(
'posts_per_page' => $number,
'post_status' => 'publish',
'post_type' => 'product',
'no_found_rows' => 1,
'order' => $order,
'meta_query' => array(),
'post_type=products&cat='.$cat
);
if ( empty( $instance['show_hidden'] ) ) {
$query_args['meta_query'][] = WC()->query->visibility_meta_query();
$query_args['post_parent'] = 0;
}
if ( ! empty( $instance['hide_free'] ) ) {
$query_args['meta_query'][] = array(
'key' => '_price',
'value' => 0,
'compare' => '>',
'type' => 'DECIMAL',
);
}
$query_args['meta_query'][] = WC()->query->stock_status_meta_query();
$query_args['meta_query'] = array_filter( $query_args['meta_query'] );
switch ( $show ) {
case 'featured' :
$query_args['meta_query'][] = array(
'key' => '_featured',
'value' => 'yes'
);
break;
case 'onsale' :
$product_ids_on_sale = wc_get_product_ids_on_sale();
$product_ids_on_sale[] = 0;
$query_args['post__in'] = $product_ids_on_sale;
break;
}
switch ( $orderby ) {
case 'price' :
$query_args['meta_key'] = '_price';
$query_args['orderby'] = 'meta_value_num';
break;
case 'rand' :
$query_args['orderby'] = 'rand';
break;
case 'sales' :
$query_args['meta_key'] = 'total_sales';
$query_args['orderby'] = 'meta_value_num';
break;
default :
$query_args['orderby'] = 'date';
}
return new WP_Query( apply_filters( 'woocommerce_products_widget_query_args', $query_args ) );
}
/**
* widget function.
*
* #see WP_Widget
*
* #param array $args
* #param array $instance
*/
public function widget( $args, $instance ) {
if ( $this->get_cached_widget( $args ) ) {
return;
}
ob_start();
if ( ( $products = $this->get_products( $args, $instance ) ) && $products->have_posts() ) {
$this->widget_start( $args, $instance );
echo apply_filters( 'woocommerce_before_widget_product_list', '<ul class="product_list_widget">' );
while ( $products->have_posts() ) {
$products->the_post();
wc_get_template( 'content-widget-product.php', array( 'show_rating' => false ) );
}
echo apply_filters( 'woocommerce_after_widget_product_list', '</ul>' );
$this->widget_end( $args );
}
wp_reset_postdata();
echo $this->cache_widget( $args, ob_get_clean() );
}
}
As you can see I've added line 70:
'in_cat' => array(
'type' => 'text',
'std' => __( 'Category Number', 'woocommerce' ),
'label' => __( 'In Category', 'woocommerce' )
and also at Line 101:
$cat = ! empty( $instance['in_cat'] ) ? sanitize_title( $instance['in_cat'] ) : $this->settings['in_cat']['std'];
The option is available in the widget to be able to entera category ID and it saves when I click the save button.
The bit I'm struggling with is actually applying the filter, you will see i've added to Line 110:
'post_type=products&cat='.$cat
and I've also tried:
'category_name' => $cat
But I can't get the filters to work. Could anyone point me in the right direction please?
Cheers
Chris
Product category is custom taxonomy, you need to use 'tax_query' to solve the purpose as follows,
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'term_id',
'terms' => $cat,
),
),
Here, $cat should be string/array of taxonomy terms.
Even you can use, woocommerce shortcode if it suites your requirement,
[product_category category="appliances"]
Here, 'appliances' is slug of product category.
Related
After my function.php code was modified I get a white screen when trying to go to my wordpress /wp-admin page. What could be causing the issue? Also general code improvement are welcome, as I never coded in php or wordpress before.
function.php file
<?php
function register_my_menus() {
register_nav_menus(
array(
'header-menu' => __( 'Header Menu' ),
'footer-menu1' => __( 'Footer Menu 1' ),
'footer-menu2' => __( 'Footer Menu 2' ),
'footer-menu3' => __( 'Footer Menu 3' ),
'side-menu' => __( 'Side Menu' ),
)
);
}
add_action( 'init', 'register_my_menus' );
add_theme_support( 'post-thumbnails' );
add_theme_support( 'custom-logo' );
add_filter ( 'nav_menu_css_class', 'so_37823371_menu_item_class', 10, 4 );
function so_37823371_menu_item_class ( $classes, $item, $args, $depth ){
$classes[] = 'nav-item';
return $classes;
}
add_filter( 'nav_menu_link_attributes', function($atts) {
$atts['class'] = "nav-link";
return $atts;
}, 100, 1 );
function my_theme_assets_files() {
wp_enqueue_script( 'custom-js', get_template_directory_uri(). '/js/custom.js' , [], '1.0.0' , true );
wp_localize_script( 'custom-js', 'jsh_ajax', [
'ajax_url' => admin_url( 'admin-ajax.php' )
]);
}
add_action( 'wp_enqueue_scripts', 'my_theme_assets_files' );
add_action("wp_ajax_sk_ajax_posts", "sk_ajax_posts");
add_action("wp_ajax_nopriv_sk_ajax_posts", "sk_ajax_posts");
function sk_ajax_posts() {
$cat_id = $_POST['cat_id'];
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => -1,
'cat' => $cat_id ,
// 'orderby’ => 'title',
// 'order’ => 'ASC',
);
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post();
//the_post();
$categories = get_the_category();
$category_name = $categories[0]->name;
?>
<div class="col-md-4 ">
<div class="card border-0">
<div class="image-parent">
<?php echo wp_get_attachment_image( get_post_thumbnail_id( get_the_ID() ), 'full', '', [ 'class' => 'card-img-top' ] ); ?>
<?php echo $category_name; ?>
</div>
<div class="card-body">
<!-- <h6>April 25, 2022</h6> -->
<h5 class="card-title"><?php the_title(); ?></h5>
<p class="card-text"><?php the_excerpt()?></p>
Read the article
</div>
</div>
</div>
<?php
endwhile;
echo paginate_links(array(
'total' => $loop->max_num_pages,
'prev_text' => __('Previous'),
'next_text' => __('Next')
)) . "</div>";
wp_reset_postdata();
die();
}
/*
* Creating a function to create our CPT
*/
function fisher_custom_post_type_advisor() {
// Set UI labels for Custom Post Type
$labels = array(
'name' => _x( 'Advisor\'s', 'Post Type General Name', 'twentytwentyone' ),
'singular_name' => _x( 'advisor', 'Post Type Singular Name', 'twentytwentyone' ),
'menu_name' => __( 'Advisor\'s', 'twentytwentyone' ),
'parent_item_colon' => __( 'advisor', 'twentytwentyone' ),
'all_items' => __( 'All Advisor\'s', 'twentytwentyone' ),
'view_item' => __( 'View Advisor', 'twentytwentyone' ),
'add_new_item' => __( 'Add New Advisor', 'twentytwentyone' ),
'add_new' => __( 'Add New', 'twentytwentyone' ),
'edit_item' => __( 'Edit Advisor', 'twentytwentyone' ),
'update_item' => __( 'Update Advisor', 'twentytwentyone' ),
'search_items' => __( 'Search Advisor', 'twentytwentyone' ),
'not_found' => __( 'Not Found', 'twentytwentyone' ),
'not_found_in_trash' => __( 'Not found in Trash', 'twentytwentyone' ),
);
// Set other options for Custom Post Type
$args = array(
'label' => __( 'Advisor\'s', 'twentytwentyone' ),
'description' => __( 'Advisor\' news and reviews', 'twentytwentyone' ),
'labels' => $labels,
// Features this CPT supports in Post Editor
'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'revisions' ),
// You can associate this CPT with a taxonomy or custom taxonomy.
// 'taxonomies' => array( 'genres' ),
/* A hierarchical CPT is like Pages and can have
* Parent and child items. A non-hierarchical CPT
* is like Posts.
*/
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'show_in_admin_bar' => true,
'menu_position' => 5,
'can_export' => true,
'has_archive' => true,
'rewrite' => array( 'slug' => 'advisors' ),
'exclude_from_search' => false,
'publicly_queryable' => true,
'capability_type' => 'post',
'show_in_rest' => false,
);
// Registering your Custom Post Type
register_post_type( 'all-advisors', $args );
}
/* Hook into the 'init' action so that the function
* Containing our post type registration is not
* unnecessarily executed.
*/
add_action( 'init', 'fisher_custom_post_type_advisor', 0 );
function global_notice_meta_box() {
add_meta_box(
'advisor-first-name',
__( 'Advisor Detail', 'sitepoint' ),
'global_notice_meta_box_callback',
'all-advisors'
);
}
add_action( 'add_meta_boxes', 'global_notice_meta_box' );
function global_notice_meta_box_callback( $post ) {
// Add a nonce field so we can check for it later.
wp_nonce_field( 'fisher_advisor', 'fisher_advisor' );
global $fields;
$fields = [
array (
'key' => 'first_name',
'label'=> __( 'Full Name'),
'type' => 'text'
),
array (
'key' => 'role',
'label'=> __( 'Title'),
'type' => 'text'
),
array (
'key' => 'professional_certificate_short_form',
'label'=> __( 'Professional Certifications (Short)'),
'type' => 'text'
),
array (
'key' => 'professional_certificate',
'label'=> __( 'Professional Certifications'),
'type' => 'text'
),
array (
'key' => 'adress',
'label'=> __( 'Full Address'),
'type' => 'text'
),
array (
'key' => 'city',
'label' => __( 'Location'),
'type' => 'text'
),
array (
'key' => 'phone',
'label' => __( 'Phone' ),
'type' => 'tel'
),
array (
'key' => 'email',
'label' => __( 'Email' ),
'type' => 'email'
)
];
foreach ( $fields as $field ) {
$value = get_post_meta( $post->ID, '_advisor_'. $field['key'], true );
if ( $field['key'] == 'city' ) {
$args = [ 'post_type' => 'all-locations', 'posts_per_page' => -1 ];
$locations = new WP_Query($args);
if ( $locations->have_posts() ) {
echo '<label><span>' . $field['label'] .'</span>';
echo '<select name="advisor_' . $field['key'] . '">';
while ( $locations->have_posts() ) {
$locations->the_post();
echo '<option value="' . get_the_title() . '">' . get_the_title() . '</option>';
}
echo '</select></label>';
}
} else {
$value = get_post_meta( $post->ID, '_advisor_'. $field['key'], true );
echo '<label><span>' . $field['label'] .'</span> <input type="'. $field['type'] .'" name="advisor_' . $field['key'] . '" value="' . esc_attr( $value ) . '" /></label>';
echo '<br>';
}
}
}
function save_global_notice_meta_box_data( $post_id ) {
// Check if our nonce is set.
if ( ! isset( $_POST['fisher_advisor'] ) ) {
return;
}
// Verify that the nonce is valid.
if ( ! wp_verify_nonce( $_POST['fisher_advisor'], 'fisher_advisor' ) ) {
return;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// Check the user's permissions.
if ( isset( $_POST['post_type'] ) && 'all-advisors' == $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return;
}
}
else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
}
/* OK, it's safe for us to save the data now. */
// Make sure that it is set.
$fields = [
array (
'key' => 'first_name',
'label'=> __( 'Full Name'),
'type' => 'text'
),
array (
'key' => 'role',
'label'=> __( 'Title'),
'type' => 'text'
),
array (
'key' => 'professional_certificate_short_form',
'label'=> __( 'Professional Certifications (Short)'),
'type' => 'text'
),
array (
'key' => 'professional_certificate',
'label'=> __( 'Professional Certifications'),
'type' => 'text'
),
array (
'key' => 'adress',
'label'=> __( 'Full Address'),
'type' => 'text'
),
array (
'key' => 'city',
'label' => __( 'Location'),
'type' => 'text'
),
array (
'key' => 'phone',
'label' => __( 'Phone' ),
'type' => 'tel'
),
array (
'key' => 'email',
'label' => __( 'Email' ),
'type' => 'email'
)
];
foreach ( $fields as $field ) {
if ( ! isset( $_POST['advisor_' . $field['key']] ) ) return;
$sav_field = sanitize_text_field( $_POST['advisor_' . $field['key']] );
update_post_meta( $post_id, '_advisor_' . $field['key'], $sav_field );
}
}
add_action( 'save_post', 'save_global_notice_meta_box_data' );
/*****cpt for location ***/
/*
* Creating a function to create our CPT
*/
function fisher_custom_post_type_location() {
// Set UI labels for Custom Post Type
$labels = array(
'name' => _x( 'Location\'s', 'Post Type General Name', 'twentytwentyone' ),
'singular_name' => _x( 'Location', 'Post Type Singular Name', 'twentytwentyone' ),
'menu_name' => __( 'Location\'s', 'twentytwentyone' ),
'parent_item_colon' => __( 'Location', 'twentytwentyone' ),
'all_items' => __( 'All Location\'s', 'twentytwentyone' ),
'view_item' => __( 'View Location', 'twentytwentyone' ),
'add_new_item' => __( 'Add New Location', 'twentytwentyone' ),
'add_new' => __( 'Add New', 'twentytwentyone' ),
'edit_item' => __( 'Edit Location', 'twentytwentyone' ),
'update_item' => __( 'Update Location', 'twentytwentyone' ),
'search_items' => __( 'Search Location', 'twentytwentyone' ),
'not_found' => __( 'Not Found', 'twentytwentyone' ),
'not_found_in_trash' => __( 'Not found in Trash', 'twentytwentyone' ),
);
// Set other options for Custom Post Type
$args = array(
'label' => __( 'Location\'s', 'twentytwentyone' ),
'description' => __( 'Location\' news and reviews', 'twentytwentyone' ),
'labels' => $labels,
// Features this CPT supports in Post Editor
'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'revisions' ),
// You can associate this CPT with a taxonomy or custom taxonomy.
// 'taxonomies' => array( 'genres' ),
/* A hierarchical CPT is like Pages and can have
* Parent and child items. A non-hierarchical CPT
* is like Posts.
*/
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'show_in_admin_bar' => true,
'menu_position' => 5,
'can_export' => true,
'has_archive' => true,
'rewrite' => array( 'slug' => 'locations' ),
'exclude_from_search' => false,
'publicly_queryable' => true,
'capability_type' => 'post',
'show_in_rest' => false,
);
// Registering your Custom Post Type
register_post_type( 'all-locations', $args );
}
/* Hook into the 'init' action so that the function
* Containing our post type registration is not
* unnecessarily executed.
*/
add_action( 'init', 'fisher_custom_post_type_location', 0 );
/****locatin-meta-box**** */
function global_notice_meta_box_location() {
add_meta_box(
'advisor-first-name',
__( 'Location Detail', 'sitepoint' ),
'global_notice_meta_box_location_callback',
'all-locations'
);
}
add_action( 'add_meta_boxes', 'global_notice_meta_box_location' );
function global_notice_meta_box_location_callback( $post ) {
// Add a nonce field so we can check for it later.
wp_nonce_field( 'fisher_location', 'fisher_location' );
global $fields;
$fields = [
array (
'key' => 'city',
'label'=> __( 'city'),
'type' => 'text'
),
array (
'key' => 'adress',
'label'=> __( 'adress'),
'type' => 'text'
),
array (
'key' => 'phone',
'label' => __( 'Phone' ),
'type' => 'tel'
),
array (
'key' => 'lati',
'label' => __( 'latitutde' ),
'type' => 'text'
),
array (
'key' => 'langi',
'label' => __( 'langitude' ),
'type' => 'text'
),
];
foreach ( $fields as $field ) {
$value = get_post_meta( $post->ID, '_location_'. $field['key'], true );
echo '<label><span>' . $field['label'] .'</span> <input type="'. $field['type'] .'" name="location_' . $field['key'] . '" value="' . esc_attr( $value ) . '" /></label>';
echo '<br>';
}
}
function save_global_notice_meta_box_location_data( $post_id ) {
// Check if our nonce is set.
if ( ! isset( $_POST['fisher_location'] ) ) {
return;
}
// Verify that the nonce is valid.
if ( ! wp_verify_nonce( $_POST['fisher_location'], 'fisher_location' ) ) {
return;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// Check the user's permissions.
if ( isset( $_POST['post_type'] ) && 'all-locations' == $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return;
}
}
else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
}
/* OK, it's safe for us to save the data now. */
// Make sure that it is set.
$fields = [
array (
'key' => 'city',
'label'=> __( 'city'),
'type' => 'text'
),
array (
'key' => 'adress',
'label'=> __( 'adress'),
'type' => 'text'
),
array (
'key' => 'phone',
'label' => __( 'Phone' ),
'type' => 'tel'
),
array (
'key' => 'lati',
'label' => __( 'latitutde' ),
'type' => 'text'
),
array (
'key' => 'langi',
'label' => __( 'langitude' ),
'type' => 'text'
),
];
foreach ( $fields as $field ) {
if ( ! isset( $_POST['location_' . $field['key']] ) ) return;
$sav_field = sanitize_text_field( $_POST['location_' . $field['key']] );
update_post_meta( $post_id, '_location_' . $field['key'], $sav_field );
}
}
When the below was added, I started getting a blank screen for wordpress when I go to /wp-admin
add_action( 'save_post', 'save_global_notice_meta_box_location_data' );
?>
<?php
//SETTING UP THE PAGE
function set_page() {
add_menu_page('Social Media Links', 'Social Media Links', 'manage_options', 'theme_settings', 'the_page', 'dashicons-share', 40);
}
//CALLING THE FUNCTION
add_action('admin_menu', 'set_page');?>
<?php //THE PAGE
function the_page() {?>
<link rel="stylesheet" href="<?php echo get_template_directory_uri()?>/css/bootstrap.min.css">
<legend style="background: #2271b1;color: #fff;padding: 15px 30px;margin-bottom: 60px;margin-top: 10px;padding-right: 85px;max-width: 99%;">Social media linked accounts</legend>
<div class="container"><div class="row"><div class="col-md-12">
<form method="post" action="options.php">
<?php settings_fields('theme_settings'); ?>
<?php $options = get_option('theme_settings'); ?>
<?php if ($_REQUEST['settings-updated']) : ?>
<div class="updated">
<p><strong class="alret">
<?php _e('Options saved'); ?>
</strong></p>
</div>
<?php endif; ?>
<div class="the-container">
<div id="social" class="container tab-pane fade active show"><br>
<fieldset>
<?php $social_arr = ['facebook','twitter','linkedin','youtube'];
foreach($social_arr as $social){?>
<div class="form-group form_builder_row facebook_container row">
<div class="col-md-2 form_builder_col">
<label class="control-label <?php echo $social;?>" for="<?php echo $social;?>">
<?php echo ucfirst($social);?>:</label>
</div>
<div class="col-md-6 form_builder_col">
<input type="text" class=" form_builder_field form-control input-text field_<?php echo $social;?>" id="<?php echo $social;?>" name="theme_settings[<?php echo $social;?>]" value="<?php echo $options[$social];?>" placeholder="<?php echo ucfirst($social);?>">
</div></div>
<?php }?>
</fieldset>
</div>
</div>
<p class="mt-4">
<input name="theme_settings[submit]" id="submit" value="Save Changes" type="submit" class="button button-primary btn-md ml-3">
</p>
</form>
</div></div></div>
<?php } ?>
<?php
//REGISTERING SETTINGS AND FIELDS
function register_settings_and_fields() {
register_setting('theme_settings','theme_settings');
}
add_action('admin_init', 'register_settings_and_fields');
?>
Have you opened wp-config.php? and set WP_DEBUG to true; this can show some errors more intuitively
Don't use function names like this the_page set_page use a prefix before function name e.g.: lefty_wp_set_page , lefty_wp_the_page or give a function a meaningful name, don't just copy paste things from internet, do some modifications in it to avoid conflicts.
I create a function to add different shiping prices foreach user, all works fine for only one user (the first on the list), but i can't get to make the select options foreach user, it only shows 1 option with all the user in it.
the problem is integrate the foreach in here: 'test' => array. It creates the html elemnt but only 1 and not 1 foreach user
my code:
class WC_Shipping_click extends WC_Shipping_Method {
public function __construct( $instance_id = 0 ) {
$args = array(
'role' => '',
'orderby' => 'user_nicename',
'order' => 'ASC'
);
$users = get_users( $args );
foreach ( $users as $user ){
$userinfo .= '['.$user->precio.','.$user->first_name.'] ';
}
$this->id = 'click_method';
$this->instance_id = absint( $instance_id );
$this->method_title = __( 'Click Shipping Method' );
$this->method_description = __( 'Click Shipping' );
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->instance_form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable' ),
'type' => 'checkbox',
'label' => __( 'Enable this shipping method' ),
'default' => 'yes',
),
'test' => array(
'title' => __( 'Prueba de array' ),
'description' => $user->first_name,
'type' => 'select',
'options' => array( ''.$userinfo.'' => ''.$userinfo'',),
'label' => __( 'Some field' ),
'required' => true,
)
)
);
$this->enabled = $this->get_option( 'enabled' );
$this->prueba = $this->get_option( 'prueba' );
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
* #param array $package (default: array())
*/
public function calculate_shipping( $package = array() ) {
$this->add_rate( array(
'id' => $this->id . $this->instance_id,
'label' => $this->title,
'cost' => $this->test,
) );
}
}
This is the scope of your foreach()
foreach ( $users as $user ){
$userinfo .= '['.$user->precio.','.$user->first_name.'] ';
}
Nothing that is below will fall into this foreach() loop.
I am modifying a wordpress theme 'jobify' . In their demo they have a 'search hero' widget with a button which takes you to a jobs listings page. Inspecting in chrome:
<form class="job_search_form job_search_form--flat"
action="https://jobify-demos.astoundify.com/classic/find-a-job/"
method="GET">
Their 'find-a-job' page which you get taken to with the button has google maps which I don't want. So I have created a new [jobs] page I named 'job-search' without the map. If I edit the above url to that in chrome inspector then the button outputs the search results correctly on my new page. following this
I have now spent 2 days going through all the widget php code trying to find where I change that GET command url on this widget button from 'find-a-job' to 'job-search'. Adjusting this on a newly made search page seems straightforward as seen on this SO question
I have read about customising their widgets here and thought it would be in the class-widget-search-hero.php file (below). I have also checked its scss file but don't see anything there. So many hours looking, is it something as simple as deleting one of the two [jobs] pages? Thank you.
<?php
/**
* Home: Search Hero
*
* #package Jobify
* #category Widget
* #since 3.0.0
*/
class Jobify_Widget_Search_Hero extends Jobify_Widget {
public function __construct() {
$this->widget_description = __( 'Display a "hero" search area.', 'jobify' );
$this->widget_id = 'jobify_widget_search_hero';
$this->widget_cssclass = 'widget--home-hero-search';
$this->widget_name = __( 'Jobify - Page: Search Hero', 'jobify' );
$this->control_ops = array(
'width' => 400,
);
$this->settings = array(
'home widgetized' => array(
'std' => __( 'Homepage/Widgetized', 'jobify' ),
'type' => 'widget-area',
),
'height' => array(
'type' => 'select',
'std' => 'medium',
'label' => __( 'Hero Height', 'jobify' ),
'options' => array(
'small' => __( 'Small', 'jobify' ),
'medium' => __( 'Medium', 'jobify' ),
'large' => __( 'Large', 'jobify' ),
),
),
'margin' => array(
'type' => 'checkbox',
'std' => 1,
'label' => __( 'Add standard spacing above/below widget', 'jobify' ),
),
'text_color' => array(
'type' => 'colorpicker',
'std' => '#ffffff',
'label' => __( 'Text Color:', 'jobify' ),
),
'title' => array(
'type' => 'text',
'std' => '',
'label' => __( 'Title:', 'jobify' ),
),
'description' => array(
'type' => 'text',
'std' => '',
'label' => __( 'Description:', 'jobify' ),
'rows' => 5,
),
'image' => array(
'type' => 'image',
'std' => '',
'label' => __( 'Background Image:', 'jobify' ),
),
'background_position' => array(
'type' => 'select',
'std' => 'center center',
'label' => __( 'Image Position:', 'jobify' ),
'options' => array(
'left top' => __( 'Left Top', 'jobify' ),
'left center' => __( 'Left Center', 'jobify' ),
'left bottom' => __( 'Left Bottom', 'jobify' ),
'right top' => __( 'Right Top', 'jobify' ),
'right center' => __( 'Right Center', 'jobify' ),
'right bottom' => __( 'Right Bottom', 'jobify' ),
'center top' => __( 'Center Top', 'jobify' ),
'center center' => __( 'Center Center', 'jobify' ),
'center bottom' => __( 'Center Bottom', 'jobify' ),
'center top' => __( 'Center Top', 'jobify' ),
),
),
'cover_overlay' => array(
'type' => 'checkbox',
'std' => 1,
'label' => __( 'Use transparent overlay', 'jobify' ),
),
);
if ( jobify()->get( 'wp-job-manager-resumes' ) ) {
$what = array(
'what' => array(
'type' => 'select',
'std' => 'job',
'label' => __( 'Search:', 'jobify' ),
'options' => array(
'job' => __( 'Jobs', 'jobify' ),
'resume' => __( 'Resumes', 'jobify' ),
),
),
);
$this->settings = $what + $this->settings;
}
parent::__construct();
}
function widget( $args, $instance ) {
extract( $args );
$text_align = isset( $instance['text_align'] ) ? esc_attr( $instance['text_align'] ) : 'left';
$background_position = isset( $instance['background_position'] ) ? esc_attr( $instance['background_position'] ) : 'center center';
$overlay = isset( $instance['cover_overlay'] ) && 1 == $instance['cover_overlay'] ? 'has-overlay' : 'no-overlay';
$margin = isset( $instance['margin'] ) && 1 == $instance['margin'] ? true : false;
$height = isset( $instance['height'] ) ? esc_attr( $instance['height'] ) : 'medium';
if ( ! $margin ) {
$before_widget = str_replace( 'widget--home ', 'widget--home widget--home--no-margin ', $before_widget );
}
$image = isset( $instance['image'] ) ? esc_url( $instance['image'] ) : null;
$content = $this->assemble_content( $instance );
$what = isset( $instance['what'] ) ? esc_attr( $instance['what'] ) : 'job';
global $is_flat;
$is_flat = true;
ob_start();
?>
<?php echo $before_widget; ?>
<div class="hero-search hero-search--<?php echo esc_attr( $overlay ); ?> hero-search--height-<?php echo esc_attr( $height ); ?>" style="background-image:url(<?php echo $image; ?>); ?>; background-position: <?php echo $background_position; ?>">
<div class="container">
<?php echo $content; ?>
<?php locate_template( array( $what . '-filters-flat.php' ), true, false ); ?>
</div>
</div>
<?php echo $after_widget; ?>
<?php
$content = ob_get_clean();
echo apply_filters( $this->widget_id, $content );
}
private function assemble_content( $instance ) {
$text_color = isset( $instance['text_color'] ) ? esc_attr( $instance['text_color'] ) : '#fff';
$title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
$content = isset( $instance['description'] ) ? $instance['description'] : '';
$output = '<div class="hero-search__content" style="color:' . $text_color . '">';
$output .= '<h2 class="hero-search__title" style="color:' . $text_color . '">' . $title . '</h2>';
$output .= wpautop( $content );
$output .= '</div>';
return $output;
}
}
The solution (if not technical answer) was actually very easy once found.
After reading this tutorial and seeing the line:
$action_page_id = get_option('job_manager_jobs_page_id');
Then searching "job_manager_jobs_page_id" and finding this on github I discovered it exists under the job manager settings /wp-admin/edit.php?post_type=job_listing&page=job-manager-settings#settings-job_pages where you just change the 'Job Listings' page in the drop down from 'find a job' to my new 'job search' page. All working.
I'm trying to add the job search functionality found at the top of this website: https://jobify-demos.astoundify.com/classic/ to my own WP theme I am building.
I've identified that this 'Search Hero Strip' is a widget which needs installing into my theme and then I guess I need to create a widetized area in my own theme so I can add this.
I believe this is the widget from the theme:
<?php
/**
* Home: Search Hero
*
* #package Jobify
* #category Widget
* #since 3.0.0
*/
class Jobify_Widget_Search_Hero extends Jobify_Widget {
public function __construct() {
$this->widget_description = __( 'Display a "hero" search area.', 'jobify' );
$this->widget_id = 'jobify_widget_search_hero';
$this->widget_cssclass = 'widget--home-hero-search';
$this->widget_name = __( 'Jobify - Page: Search Hero', 'jobify' );
$this->control_ops = array(
'width' => 400
);
$this->settings = array(
'home widgetized' => array(
'std' => __( 'Homepage/Widgetized', 'jobify' ),
'type' => 'widget-area'
),
'height' => array(
'type' => 'select',
'std' => 'medium',
'label' => __( 'Hero Height', 'jobify' ),
'options' => array(
'small' => __( 'Small', 'jobify' ),
'medium' => __( 'Medium', 'jobify' ),
'large' => __( 'Large', 'jobify' )
)
),
'margin' => array(
'type' => 'checkbox',
'std' => 1,
'label' => __( 'Add standard spacing above/below widget', 'jobify' )
),
'text_color' => array(
'type' => 'colorpicker',
'std' => '#ffffff',
'label' => __( 'Text Color:', 'jobify' )
),
'title' => array(
'type' => 'text',
'std' => '',
'label' => __( 'Title:', 'jobify' )
),
'description' => array(
'type' => 'text',
'std' => '',
'label' => __( 'Description:', 'jobify' ),
'rows' => 5
),
'image' => array(
'type' => 'image',
'std' => '',
'label' => __( 'Background Image:', 'jobify' )
),
'background_position' => array(
'type' => 'select',
'std' => 'center center',
'label' => __( 'Image Position:', 'jobify' ),
'options' => array(
'left top' => __( 'Left Top', 'jobify' ),
'left center' => __( 'Left Center', 'jobify' ),
'left bottom' => __( 'Left Bottom', 'jobify' ),
'right top' => __( 'Right Top', 'jobify' ),
'right center' => __( 'Right Center', 'jobify' ),
'right bottom' => __( 'Right Bottom', 'jobify' ),
'center top' => __( 'Center Top', 'jobify' ),
'center center' => __( 'Center Center', 'jobify' ),
'center bottom' => __( 'Center Bottom', 'jobify' ),
'center top' => __( 'Center Top', 'jobify' )
)
),
'cover_overlay' => array(
'type' => 'checkbox',
'std' => 1,
'label' => __( 'Use transparent overlay', 'jobify' )
),
);
if ( jobify()->get( 'wp-job-manager-resumes' ) ) {
$what = array(
'what' => array(
'type' => 'select',
'std' => 'job',
'label' => __( 'Search:', 'jobify' ),
'options' => array(
'job' => __( 'Jobs', 'jobify' ),
'resume' => __( 'Resumes', 'jobify' )
)
)
);
$this->settings = $what + $this->settings;
}
parent::__construct();
}
function widget( $args, $instance ) {
extract( $args );
$text_align = isset( $instance[ 'text_align' ] ) ? esc_attr( $instance[ 'text_align' ] ) : 'left';
$background_position = isset( $instance[ 'background_position' ] ) ? esc_attr( $instance[ 'background_position' ] ) : 'center center';
$overlay = isset( $instance[ 'cover_overlay' ] ) && 1 == $instance[ 'cover_overlay' ] ? 'has-overlay' : 'no-overlay';
$margin = isset( $instance[ 'margin' ] ) && 1 == $instance[ 'margin' ] ? true : false;
$height = isset( $instance[ 'height' ] ) ? esc_attr( $instance[ 'height' ] ) : 'medium';
if ( ! $margin ) {
$before_widget = str_replace( 'widget--home ', 'widget--home widget--home--no-margin ', $before_widget );
}
$image = isset( $instance[ 'image' ] ) ? esc_url( $instance[ 'image' ] ) : null;
$content = $this->assemble_content( $instance );
$what = isset( $instance[ 'what' ] ) ? esc_attr( $instance[ 'what' ] ) : 'job';
global $is_flat;
$is_flat = true;
ob_start();
?>
<?php echo $before_widget; ?>
<div class="hero-search hero-search--<?php echo esc_attr( $overlay ); ?> hero-search--height-<?php echo esc_attr( $height ); ?>" style="background-image:url(<?php echo $image; ?>); ?>; background-position: <?php echo $background_position; ?>">
<div class="container">
<?php echo $content; ?>
<?php locate_template( array( $what . '-filters-flat.php' ), true, false ); ?>
</div>
</div>
<?php echo $after_widget; ?>
<?php
$content = ob_get_clean();
echo apply_filters( $this->widget_id, $content );
}
private function assemble_content( $instance ) {
$text_color = isset( $instance[ 'text_color' ] ) ? esc_attr( $instance[ 'text_color' ] ) : '#fff';
$title = isset( $instance[ 'title' ] ) ? esc_attr( $instance[ 'title' ] ) : '';
$content = isset( $instance[ 'description' ] ) ? $instance[ 'description' ] : '';
$output = '<div class="hero-search__content" style="color:' . $text_color . '">';
$output .= '<h2 class="hero-search__title" style="color:' . $text_color . '">' . $title . '</h2>';
$output .= wpautop( $content );
$output .= '</div>';
return $output;
}
}
I've tried to add this inside the functions file but it just produces errors.
I know this might come across as basic and im sure im missing somehting important, but im a bit stuck.
I'd either want to do it as a widget or strip out the search form from it and just add it to my home template page - is either possibe?
OK, I'm stumped. I've searched and read several posts including the related post Checking products in cart based on category name woocommerce? from where I derived much of this code, and Woocommerce - Add filter to display (or hide) custom checkout field if product ID == # which is specific to Product IDs, not Category IDs.
I want to display the sdc_custom_checkout_field if, and only if, the target category ID (237 in this case) is in the cart.
I tried commenting out the sdc_custom_checkout_field function and using a simple test shown below, but kept getting "Nope!", so I assume the query is incorrect.
add_action( 'woocommerce_before_order_notes', 'sdc_custom_checkout_field' );
function sdc_custom_checkout_field( $checkout ) {
//Check if Product in Cart
//$product_in_cart = check_product_in_cart();
//Product is in cart so show additional fields
if ( $product_in_cart === true ) {
echo '<div id="my_custom_checkout_field"><h3>' . __( 'Duplicate Card Information' . '</h3><br>');
woocommerce_form_field( 'dupecard_location', array(
'type' => 'text',
'class' => array( 'dupecard-location form-row-wide' ),
'label' => __( 'Course Location' ),
), $checkout->get_value( 'dupecard_location' ) );
woocommerce_form_field( 'dupecard_instructor', array(
'type' => 'text',
'class' => array( 'dupecard-instructor form-row-wide' ),
'label' => __( 'Instructor Name' ),
), $checkout->get_value( 'dupecard_instructor' ) );
woocommerce_form_field( 'dupecard_requestor_name', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-name form-row-wide' ),
'label' => __( 'Requestor Name' ),
), $checkout->get_value( 'dupecard_requestor_name' ) );
woocommerce_form_field( 'dupecard_requestor_email', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-email form-row-wide' ),
'label' => __( 'Requestor Email' ),
), $checkout->get_value( 'dupecard_requestor_email' ) );
woocommerce_form_field( 'dupecard_requestor_phone', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-phone form-row-wide' ),
'label' => __( 'Requestor Phone' ),
), $checkout->get_value( 'dupecard_requestor_phone' ) );
echo '</div>';
}
}
function check_product_in_cart() {
//Check to see if user has product in cart
global $woocommerce;
//assign default negative value
$product_in_cart = false;
// start cart items fetch loop
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$terms = get_the_terms( $_product->id, 'product_cat' );
// second level loop search, in case some items have several categories
$cat_ids = array();
foreach ($terms as $term) {
$cat_ids[] = $term->term_id;
}
if(in_array(237, (array)$cat_ids)) {
//category is in cart!
$product_in_cart = true;
}
}
return $product_in_cart;
}
Here’s the test snippet:
if ($item_in_cart === true) {echo 'YES';}
else {echo 'Nope!';}
I also replaced
$item_in_cart
with
$product_in_cart
but it made no difference.
********** EDIT RESPONSE TO #PRAFULLA **********
#Prafulla - thanks for your input. I appreciate it. I modified my snippet as follows, incorporating yours, but was unable to get it to work. I'm a PHP newbie, so, no surprise. Do you have additional advice?
add_action( 'woocommerce_before_order_notes', 'sdc_custom_checkout_field' );
function sdc_custom_checkout_field( $checkout ) {
//Check if Product in Cart
$your_product_category = is_category_in_cart();
//Product is in cart so show additional fields
if ( $your_product_category === true ) {
echo '<div id="my_custom_checkout_field"><h3>' . __( 'Duplicate Card Information' . '</h3><br>');
woocommerce_form_field( 'dupecard_location', array(
'type' => 'text',
'class' => array( 'dupecard-location form-row-wide' ),
'label' => __( 'Course Location' ),
), $checkout->get_value( 'dupecard_location' ) );
woocommerce_form_field( 'dupecard_instructor', array(
'type' => 'text',
'class' => array( 'dupecard-instructor form-row-wide' ),
'label' => __( 'Instructor Name' ),
), $checkout->get_value( 'dupecard_instructor' ) );
woocommerce_form_field( 'dupecard_requestor_name', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-name form-row-wide' ),
'label' => __( 'Requestor Name' ),
), $checkout->get_value( 'dupecard_requestor_name' ) );
woocommerce_form_field( 'dupecard_requestor_email', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-email form-row-wide' ),
'label' => __( 'Requestor Email' ),
), $checkout->get_value( 'dupecard_requestor_email' ) );
woocommerce_form_field( 'dupecard_requestor_phone', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-phone form-row-wide' ),
'label' => __( 'Requestor Phone' ),
), $checkout->get_value( 'dupecard_requestor_phone' ) );
echo '</div>';
}
}
function is_category_in_cart( $your_product_category = 237 ){
global $woocommerce;
$products_in_cart = $woocommerce->cart->get_cart();
$product_types_in_cart = array_column( $products_in_cart, 'data' );
//if ( $product_types_in_cart[0]->product_type == 'subscription' ) { this is what I have tested
if ( $product_types_in_cart[0]->product_cat == $your_product_category ) {
return true;
}
return $your_product_category;
}
After much work, research, and the assistance of some paid help on another website, this is the working result:
// Add the field to the checkout
add_action( 'woocommerce_before_order_notes', 'sdc_custom_checkout_field' );
function sdc_custom_checkout_field( $checkout ) {
if( check_product_category() ){
echo '<div id="sdc_checkout_field"><h3>' . __( 'Duplicate Card Information' . '</h3><br>');
woocommerce_form_field( 'dupecard_location', array(
'type' => 'text',
'required' => true,
'class' => array( 'dupecard-location form-row-wide' ),
'label' => __( 'Course Location' ),
), $checkout->get_value( 'dupecard_location' ) );
woocommerce_form_field( 'dupecard_instructor', array(
'type' => 'text',
'required' => true,
'class' => array( 'dupecard-instructor form-row-wide' ),
'label' => __( 'Instructor Name' ),
), $checkout->get_value( 'dupecard_instructor' ) );
woocommerce_form_field( 'dupecard_requestor_name', array(
'type' => 'text',
'required' => true,
'class' => array( 'dupecard-requestor-name form-row-wide' ),
'label' => __( 'Requestor Name' ),
), $checkout->get_value( 'dupecard_requestor_name' ) );
woocommerce_form_field( 'dupecard_requestor_email', array(
'type' => 'text',
'required' => true,
'class' => array( 'dupecard-requestor-email form-row-wide' ),
'label' => __( 'Requestor Email' ),
), $checkout->get_value( 'dupecard_requestor_email' ) );
woocommerce_form_field( 'dupecard_requestor_phone', array(
'type' => 'text',
'required' => true,
'class' => array( 'dupecard-requestor-phone form-row-wide' ),
'label' => __( 'Requestor Phone' ),
), $checkout->get_value( 'dupecard_requestor_phone' ) );
echo '</div>';
}
}
function check_product_category(){
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if( is_category_in_cart( $product_id ) ){
return true;
}
}
return false;
}
function is_category_in_cart( $product_id ){
return has_term( 237,'product_cat', get_post( $product_id ) );
}
/*Save to DB as post meta*/
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['dupecard_location'] ) ) {
update_post_meta( $order_id, 'dupecard_location', sanitize_text_field( $_POST['dupecard_location'] ) );
}
if ( ! empty( $_POST['dupecard_instructor'] ) ) {
update_post_meta( $order_id, 'dupecard_instructor', sanitize_text_field( $_POST['dupecard_instructor'] ) );
}
if ( ! empty( $_POST['dupecard_requestor_name'] ) ) {
update_post_meta( $order_id, 'dupecard_requestor_name', sanitize_text_field( $_POST['dupecard_requestor_name'] ) );
}
if ( ! empty( $_POST['dupecard_requestor_email'] ) ) {
update_post_meta( $order_id, 'dupecard_requestor_email', sanitize_text_field( $_POST['dupecard_requestor_email'] ) );
}
if ( ! empty( $_POST['dupecard_requestor_phone'] ) ) {
update_post_meta( $order_id, 'dupecard_requestor_phone', sanitize_text_field( $_POST['dupecard_requestor_phone'] ) );
}
}
This is how I get the job done in my case , please try it and note where you need to give your input on this code as It is not written for direct use.
function is_category_in_cart( $your_product_category = null ){
global $woocommerce;
$products_in_cart = $woocommerce->cart->get_cart();
$product_types_in_cart = array_column( $products_in_cart, 'data' );
//if ( $product_types_in_cart[0]->product_type == 'subscription' ) { this is what I have tested
if ( $product_types_in_cart[0]->product_cat == $your_product_category ) {
return true;
}
}