I'm working with a custom function for page navigation in Wordpress, based on the one used in the Bones theme (http://themble.com/bones). The function outputs numbered page links, but also outputs both previous and next page buttons, even when you are on the first or last page. I want to adapt it to only show the previous page button when you are not on the first page, and only show the next page button when you are not on the last page. Hopefully that makes sense!
Here's the function:
function custom_page_navi($before = '', $after = '') {
global $wpdb, $wp_query;
$request = $wp_query->request;
$posts_per_page = intval(get_query_var('posts_per_page'));
$paged = intval(get_query_var('paged'));
$numposts = $wp_query->found_posts;
$max_page = $wp_query->max_num_pages;
if ( $numposts <= $posts_per_page ) { return; }
if(empty($paged) || $paged == 0) {
$paged = 1;
}
$pages_to_show = 7;
$pages_to_show_minus_1 = $pages_to_show-1;
$half_page_start = floor($pages_to_show_minus_1/2);
$half_page_end = ceil($pages_to_show_minus_1/2);
$start_page = $paged - $half_page_start;
if($start_page <= 0) {
$start_page = 1;
}
$end_page = $paged + $half_page_end;
if(($end_page - $start_page) != $pages_to_show_minus_1) {
$end_page = $start_page + $pages_to_show_minus_1;
}
if($end_page > $max_page) {
$start_page = $max_page - $pages_to_show_minus_1;
$end_page = $max_page;
}
if($start_page <= 0) {
$start_page = 1;
}
echo $before.'<nav class="pagination"><ol class="custom_page_navi">'."";
if ($start_page >= 2 && $pages_to_show < $max_page) {
$first_page_text = __( "First");
echo '<li class="cpn-first-page-link">'.$first_page_text.'</li>';
}
echo '<li class="cpn-prev-link">';
previous_posts_link('');
echo '</li>';
for($i = $start_page; $i <= $end_page; $i++) {
if($i == $paged) {
echo '<li class="cpn-current">'.$i.'</li>';
} else {
echo '<li>'.$i.'</li>';
}
}
echo '<li class="cpn-next-link">';
next_posts_link('');
echo '</li>';
if ($end_page < $max_page) {
$last_page_text = __( "Last");
echo '<li class="cpn-last-page-link">'.$last_page_text.'</li>';
}
echo '</ol></nav>'.$after."";
}
Any ideas?
Why not just leave it? Also Bones official Git can be helpful, open a support issue there with this question. Anyways try this untested code :
Change this:
if ($end_page < $max_page) {
$last_page_text = __( "Last", 'bonestheme' );
echo '<li class="bpn-last-page-link">'.$last_page_text.'</li>';
}
To this:
if ($end_page < $max_page && != $max_page) {
$last_page_text = __( "Last", 'bonestheme' );
echo '<li class="bpn-last-page-link">'.$last_page_text.'</li>';
}
Related
Based on "How to add variation stock status to Woocommerce product variation dropdown" answer, I have made some code that shows the custom attribute of a variable product and its presence in the store:
// Function that will check the stock status and display the corresponding additional text
function get_stock_status_text($product, $name, $term_slug) {
foreach($product - > get_available_variations() as $variation) {
if ($variation['attributes'][$name] == $term_slug)
$stock = $variation['is_in_stock'];
}
return $stock == 1 ? '' : ' - out of stock';
}
// The hooked function that will add the stock status to the dropdown options elements.
add_filter('woocommerce_dropdown_variation_attribute_options_html', 'show_stock_status_in_dropdown', 10, 2);
function show_stock_status_in_dropdown($html, $args) {
// Only if there is a unique variation attribute (one dropdown)
if (sizeof($args['product'] - > get_variation_attributes()) == 1):
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute']; // The product attribute taxonomy
$name = $args['name'] ? $args['name'] : 'attribute_'.sanitize_title($attribute);
$id = $args['id'] ? $args['id'] : sanitize_title($attribute);
$class = $args['class'];
$show_option_none = $args['show_option_none'] ? true : false;
$show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __('Select size', 'woocommerce');
if (empty($options) && !empty($product) && !empty($attribute)) {
$attributes = $product - > get_variation_attributes();
$options = $attributes[$attribute];
}
$html = '<select id="'.esc_attr($id).
'" class="'.esc_attr($class).
'" name="'.esc_attr($name).
'" data-attribute_name="attribute_'.esc_attr(sanitize_title($attribute)).
'" data-show_option_none="'.($show_option_none ? 'yes' : 'no').
'">';
$html. = '<option value="">'.esc_html($show_option_none_text).
'</option>';
if (!empty($options)) {
if ($product && taxonomy_exists($attribute)) {
$terms = wc_get_product_terms($product - > get_id(), $attribute, array('fields' => 'all'));
foreach($terms as $term) {
if (in_array($term - > slug, $options)) {
// HERE Added the function to get the text status
$stock_status = get_stock_status_text($product, $name, $term - > slug);
$html. = '<option value="'.esc_attr($term - > slug).
'" '.selected(sanitize_title($args['selected']), $term - > slug, false).
'>'.esc_html(apply_filters('woocommerce_variation_option_name', $term - > name).$stock_status).
'</option>';
}
}
} else {
foreach($options as $option) {
$selected = sanitize_title($args['selected']) === $args['selected'] ? selected($args['selected'], sanitize_title($option), false) : selected($args['selected'], $option, false);
// HERE Added the function to get the text status
$stock_status = get_the_stock_status($product, $name, $option);
$html. = '<option value="'.esc_attr($option).
'" '.$selected.
'>'.esc_html(apply_filters('woocommerce_variation_option_name', $option).$stock_status).
'</option>';
}
}
}
$html. = '</select>';
endif;
return $html;
}
On a single product page, I show related products. How to show this attribute (its presence in the store) in the form of a label in related products?
For example:
The product's name
Price - $25
Sizes available: L, XL
Try this code, I hooked into the woocommerce_after_shop_loop_item and displayed the product attributes. Right now it only works for the size attribute. It is showing the Large, Medium, Small. If you want to show L, XL, M, etc. just edit the size attribute.
add_action( 'woocommerce_after_shop_loop_item', 'mamham_woocommerce_after_shop_loop_item', 10);
function mamham_woocommerce_after_shop_loop_item() {
global $product;
// Bail if not in the single product page.
if ( ! is_product() ) return;
// Prduct attributes which you want to show.
// Attributes to show in the slug.
// 'attribute slug' => 'Text shown';
$show_attributes = array(
'size' => 'Sizes available:',
);
// Get the slugs.
$show_slugs = array_keys( $show_attributes );
// Get product type.
$product_type = $product->get_type();
if( 'simple' === $product_type ) {
$product_attributes = $product->get_attributes();
foreach( $product_attributes as $key => $product_attribute ) {
$slug = substr( $key, 3 );
if ( in_array( $slug, $show_slugs, TRUE ) ) {
$terms = $product_attribute->get_terms();
$terms_output = wp_list_pluck( $terms, 'name');
$terms_output = implode(', ', $terms_output );
echo esc_html( "${show_attributes[$slug]} ${terms_output}" );
}
}
} elseif ( 'variable' === $product_type ) {
$product_variations = $product->get_available_variations();
foreach ( $product_variations as $product_variation ) {
if ( $product_variation['is_in_stock'] && isset( $product_variation['attributes']['attribute_pa_size'] )) {
$terms_output[] = ucwords( $product_variation['attributes']['attribute_pa_size'] );
}
}
if ( ! empty( $terms_output) ) {
$terms_output = implode(', ', $terms_output );
echo esc_html( "Sizes available: ${terms_output}" );
}
}
}
Here is the screenshot, I have storefront theme and WooCommerce installed.
Im trying to switch the menu when the user is on a specific product category.
Ive got the code working on other parts of the site fine but for some reason it doesn't work here :/
get_queried_object() returns null
Its currently defaulting to the last menu 'MAIN' as none of the if statements went off but I don't know why.
Im trying to identify the page id or name outside the loop but whatever I try it doesn't work.
See Code:
$this_category = get_queried_object();
if(is_product_category('cat1') || $this_category->parent == 125) {
echo 'cat1';
$whichmenu = 127;
} elseif(is_product_category('cat2') || $this_category->parent == 86) {
echo 'cat2';
$whichmenu = 79;
} elseif (is_product_category('cat3') || $this_category->parent == 85) {
echo 'cat3';
$whichmenu = 78;
} elseif (is_product_category('cat4') || $this_category->parent == 90) {
echo 'cat4';
$whichmenu = 83;
} elseif (is_product_category('cat5') || $this_category->parent == 89 || has_term('mrl')) {
echo 'cat5';
$whichmenu = 82;
} elseif (is_product_category('cat6') || $this_category->parent == 88) {
echo 'cat6';
$whichmenu = 81;
} elseif (is_product_category('cat7') || $this_category->parent == 87) {
echo 'cat7';
$whichmenu = 80;
} else {
echo 'MAIN';
$whichmenu = 77;
}
wp_nav_menu( array(
'theme_location' => 'primary',
'container_class' => 'main-menu',
'menu_id' => 'primary-menu-mobile',
'menu' => $whichmenu,
'items_wrap' => '<ul id=%1$s class=%2$s>%3$s</ul>',
'walker' => new WowmallMainMenuWalker,
) );
I use $this_category->parent to identify if the child category is a child of a certain parent and if so change the menu.
Any help would be greatly appreciated :)
Cheers
Josh
Solved use wp_get_referer() to get the url that its referred from.
Here is the code for place ads after 1st, 2nd, 3d paragraph. but i want to place ad just before last paragraph of my wordpress post. is there any way to do this ?
<?php
add_filter( 'the_content', 'prefix_insert_post_ads' );
function prefix_insert_post_ads( $content ) {
$ad_code = '<div>Ads code goes here</div>';
if ( is_single() && ! is_admin() ) {
return prefix_insert_after_paragraph( $ad_code, 1, $content );
}
return $content;
}
// Parent Function that makes the magic happen
function prefix_insert_after_paragraph( $insertion, $paragraph_id, $content ) {
$closing_p = '</p>';
$paragraphs = explode( $closing_p, $content );
foreach ($paragraphs as $index => $paragraph) {
if ( trim( $paragraph ) ) {
$paragraphs[$index] .= $closing_p;
}
if ( $paragraph_id == $index + 1 ) {
$paragraphs[$index] .= $insertion;
}
}
return implode( '', $paragraphs );
}
?>
add_filter('the_content', 'ad_signal');
function ad_signal($content)
{
if (!is_single()) return $content;
$tent = get_the_content();
$content = explode("</p>", $content);
$ss = count($content);
$ns = $ss-1; //**before last paragraph in wordpress **
$new_content = '';
for ($i = 0; $i < count($content); $i++) {
if ($i == $ns ) {
$new_content.= ' <div style="text-align:center;">';
$new_content.= '<h1> Your ads Here ! </h1>';
$new_content.= '</div>';
}
$new_content.= $content[$i] . "</p>";
}
return $new_content;
}
I have set Adsense code by this Code in my sites named All BD Results and etunescafe. You just add this code in your sites functions.php N.B. Before adding the code please replace your or add your adsense code. It will be good enough to go through this post. How to Set Adsense Ads Right Before The Last Paragraph
function ads_added_above_last_p($text) {
if( is_single() ) :
$ads_text = '<div class="a" style="text-align: center;">Your Adsense Code</div>';
if($pos1 = strrpos($text, '<p>')){
$text1 = substr($text, 0, $pos1);
$text2 = substr($text, $pos1);
$text = $text1 . $ads_text . $text2;
}
endif;
return $text;
}
add_filter('the_content', 'ads_added_above_last_p');
Hey guys so I ran into the same problem and managed to solve it incorporating your answers into one.
The function that does all the processing is changed so that is counts all the paragraphs created by the explode method. Then another if statement is added to evaluate when you are at the desired location.
function prefix_insert_after_paragraph( $insertion, $paragraph_id, $content ) {
$closing_p = '</p>';
$paragraphs = explode( $closing_p, $content );
$last_paragraph_index = count($paragraphs);
foreach ($paragraphs as $index => $paragraph) {
if ( trim( $paragraph ) ) {
$paragraphs[$index] .= $closing_p;
}
if ( $paragraph_id == $index + 1 ) {
$paragraphs[$index] .= $insertion;
}
else if( $last_paragraph_index + $paragraph_id == $index + 1){
$paragraphs[$index] .= $insertion;
}
}
return implode( '', $paragraphs );
}
in order to use the new functionality you must call it with a negative number.
Think of the function this way, if you want to go from the top of the content you use a positive number, if you want to go from the bottom of the content you use a negative number.
Remember that even though the evaluation is for your decided spot such as before the last paragraph the condition that adds to the array uses the index which we all know is zero based.
This just means that to get after paragraph 1 you must use the number 2 when calling the function and to get to before the last paragraph you have to use -2 and so on.
Here is my example to add the a read the next post if it exists to the article
add_filter( 'the_content', 'prefix_insert_next_article_banner' );
function prefix_insert_next_article_banner( $content ) {
if ( is_single() && ! is_admin() && get_next_post_link() ) {
$next_banner = '<div class="next-banner"> <span> Read Next </span>';
$next_banner .= ' ' . get_the_title(get_adjacent_post(false,'',false)) .' ';
$next_banner .= '</div>';
return prefix_insert_after_paragraph( $next_banner, -2, $content );
}
return $content;
}
This is my function in function.php file
function getcity(){
global $wpdb;
if($_POST['state'])
{
$id=$_POST['state'];
$district = get_post_meta(get_the_ID() , 'district', true);
var_dump($district);
$result=$wpdb->get_results("SELECT * FROM districts WHERE state_id='$id'");
foreach($result as $row) {
$district_name = $row-
>district_name;
$district_id = $row->district_id;
echo '<option value="'.$district_id.'">'.$district_name.'</option>';
}
}
}
add_action("wp_ajax_nopriv_getcity", "getcity");
add_action("wp_ajax_getcity", "getcity");
I want to get current post id in this function to display selected dropdown value..
Note that $post or get_queried_object_id() do not work until the first query was fired. So these options are available only at the hook template_redirect and later. But functions.php is included much earlier (before the hook after_setup_theme) so this isn't a solution.
A function that should work pretty much anywhere would be:
$url = 'http://' . $_SERVER[ 'HTTP_HOST' ] . $_SERVER[ 'REQUEST_URI' ];
$current_post_id = url_to_postid( $url );
Here is a overview over hook execution order.
As mentioned in the comments url_to_postid may be heavy in some setups, so if your code is executed after template_redirect you better use one of the solutions below as they are most likely much faster than the snippet above:
global $post;
$id = $post->id;
or
$id = get_queried_object_id();
Here is one my function what never fail.
I don't know why WordPress not made something like this before.
/**
* Get current page ID
* #autor Ivijan-Stefan Stipic
* #version 2.0.0
**/
function get_current_page_ID(){
static $current_page_ID;
if(!$current_page_ID) return $current_page_ID;
global $post, $wp_query, $wpdb;
if(!is_null($wp_query) && isset($wp_query->post) && isset($wp_query->post->ID) && !empty($wp_query->post->ID)){
$current_page_ID = $wp_query->post->ID;
} else if(function_exists('get_the_id') && !empty(get_the_id())){
$current_page_ID = get_the_id();
}else if(!is_null($post) && isset($post->ID) && !empty($post->ID))
$current_page_ID = $post->ID;
else if( (isset($_GET['action']) && sanitize_text_field($_GET['action']) == 'edit') && $post = ((isset($_GET['post']) && is_numeric($_GET['post'])) ? absint($_GET['post']) : false))
$current_page_ID = $post;
else if($p = ((isset($_GET['p']) && is_numeric($_GET['p'])) ? absint($_GET['p']) : false))
$current_page_ID = $p;
else if($page_id = ((isset($_GET['page_id']) && is_numeric($_GET['page_id'])) ? absint($_GET['page_id']) : false))
$current_page_ID = $page_id;
else if(!is_admin() && $wpdb)
{
$actual_link = rtrim($_SERVER['REQUEST_URI'], '/');
$parts = explode('/', $actual_link);
if(!empty($parts))
{
$slug = end($parts);
if(!empty($slug))
{
if($post_id = $wpdb->get_var(
$wpdb->prepare(
"SELECT ID FROM {$wpdb->posts}
WHERE
`post_status` = %s
AND
`post_name` = %s
AND
TRIM(`post_name`) <> ''
LIMIT 1",
'publish',
sanitize_title($slug)
)
))
{
$current_page_ID = absint($post_id);
}
}
}
}
else if(!is_admin() && 'page' == get_option( 'show_on_front' ) && !empty(get_option( 'page_for_posts' ))){
$current_page_ID = get_option( 'page_for_posts' );
}
return $current_page_ID;
}
This function check all possible cases and return ID of the current page or false on the fail.
How to limit the excerpt length by paragraph, not word/char count? For example, excerpt shows only first two paragraphs, no matter how long the paragraphs are.
Thanks in advance.
Here is a function that keeps HTML tags in tact, adds a "Read More" link at the end of the excerpt and trims the excerpt after the first paragraph.
if ( ! function_exists( 'wpse0001_custom_wp_trim_excerpt' ) ) :
function wpse0001_custom_wp_trim_excerpt($wpse0001_excerpt) {
global $post;
$raw_excerpt = $wpse0001_excerpt;
if ( '' == $wpse0001_excerpt ) {
$wpse0001_excerpt = get_the_content('');
$wpse0001_excerpt = strip_shortcodes( $wpse0001_excerpt );
$wpse0001_excerpt = apply_filters('the_content', $wpse0001_excerpt);
// Here we choose how many paragraphs do we want to cutthe excerpt at, This part thanks to Clément Malet
$wpse0001_excerpt = "<p>$wpse0001_excerpt</p>";
$wanted_number_of_paragraph = 2;
$tmp = explode ('</p>', $wpse0001_excerpt);
for ($i = 0; $i < $wanted_number_of_paragraph; ++$i) {
if (isset($tmp[$i]) && $tmp[$i] != '') {
$tmp_to_add[$i] = $tmp[$i];
}
}
$wpse0001_excerpt = implode('</p>', $tmp_to_add) . '</p>';
$wpse0001_excerpt = str_replace(']]>', ']]>', $wpse0001_excerpt);
$excerpt_end = ' ' . ' » ' . sprintf(__( 'Read more about: %s »', 'pietergoosen' ), get_the_title()) . '';
$excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end);
//$pos = strrpos($wpse0001_excerpt, '</');
//if ($pos !== false)
// Inside last HTML tag
//$wpse0001_excerpt = substr_replace($wpse0001_excerpt, $excerpt_end, $pos, 0);
//else
// After the content
$wpse0001_excerpt .= $excerpt_end;
return $wpse0001_excerpt;
}
return apply_filters('wpse0001_custom_wp_trim_excerpt', $wpse0001_excerpt, $raw_excerpt);
}
endif;
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'wpse0001_custom_wp_trim_excerpt');
EDIT
Thanks to the help from #ClementMalet, I was able to tweak my function to make you choose the amount of paragraphs where you want to cut the excerpt. Please check his great answer here