I am working with this function:
if ( $id && $post && $post->post_type == 'business-areas' )
{
$pieces = explode(' ', $the_title);
$last_word = trim(strtolower(array_pop($pieces)));
if($last_word != 'jobs')
{
$the_title = $the_title . ' jobs';
}
}
return $the_title;
This is basically appending the word JOBS to any titles on a custom post type of business-areas if the last word of the title is not JOBS.
Is there a way to add a template query to this?
So basically, if the page template of the custom post is DEFAULT, do this, if the page template is not DEFAULT, don't do it.
Put this code in the functions.php file.
function add_label_to_post_title( $the_title = '' ) {
global $post;
if ($post && $post->post_type == 'business-areas' )
{
$pieces = explode(' ', $the_title);
$last_word = trim(strtolower(array_pop($pieces)));
if($last_word != 'jobs')
{
$the_title = $the_title . ' jobs';
}
}
return $the_title;
}
add_filter( 'the_title', 'add_label_to_post_title' );
Related
How to add a custom attribute in the field Contact Form 7 without javascript ?
For example, there is such a field on the page:
<input type="text" name="name" class="form-control" id="name-1" data-attr="custom" data-msg="Текст 1">
Question: is it possible to set these custom attributes (data-attr, data-msg) of fields in the admin panel?
Find the name of your field.
[text* text-21]
If the name of your field name="text-21", like in my example, add this code to functions.php file.
add_filter( 'wpcf7_form_elements', 'imp_wpcf7_form_elements' );
function imp_wpcf7_form_elements( $content ) {
$str_pos = strpos( $content, 'name="text-21"' );
if ( $str_pos !== false ) {
$content = substr_replace( $content, ' data-attr="custom" data-msg="Foo Bar 1" ', $str_pos, 0 );
}
return $content;
}
Note, it will add those attributes to all forms elements where the name is text-21, if you want prevent it then give your form element some unique name [text* unique-name]
And change the code to
add_filter( 'wpcf7_form_elements', 'imp_wpcf7_form_elements' );
function imp_wpcf7_form_elements( $content ) {
$str_pos = strpos( $content, 'name="unique-name"' );
if ( $str_pos !== false ) {
$content = substr_replace( $content, ' data-attr="custom" data-msg="Foo Bar 1" ', $str_pos, 0 );
}
return $content;
}
Here is a generic solution that doesn't involve hardcoding the field name and the attributes
add_filter( 'wpcf7_form_tag', function ( $tag ) {
$datas = [];
foreach ( (array)$tag['options'] as $option ) {
if ( strpos( $option, 'data-' ) === 0 ) {
$option = explode( ':', $option, 2 );
$datas[$option[0]] = apply_filters('wpcf7_option_value', $option[1], $option[0]);
}
}
if ( ! empty( $datas ) ) {
$id = uniqid('tmp-wpcf');
$tag['options'][] = "class:$id";
add_filter( 'wpcf7_form_elements', function ($content) use ($id, $datas) {
return str_replace($id, $name, str_replace($id.'"', '"'. wpcf7_format_atts($datas), $content));
});
}
return $tag;
} );
It works on all data attributes so you can use it like this
[text* my-name data-foo:bar data-biz:baz placeholder "Blabla"]
Output: <input type="text" name="my-name" data-foo="bar" data-biz="baz" placeholder="Blabla">
Since wpcf7 doesn't provide a way to hook into options directly the solutions uses a trick and temporary adds a uniquely generated class to the field that is then replaced in a later filter with the added attributes
If you need it to work with more than just data attributes you can whitelist some more attributes by replacing this line
if ( strpos( $option, 'data-' ) === 0 ) {
to something like the following
if ( preg_match( '/^(data-|pattern|my-custom-attribute)/', $option ) ) {
Note: wpcf7_format_atts will not output empty attributes, so make sure you give a value to your attributes
Multiple attributes can be added also. eg
add_filter( 'wpcf7_form_elements', 'imp_wpcf7_form_elements' );
function imp_wpcf7_form_elements( $content ) {
$str_pos = strpos( $content, 'name="your-email-homepage"' );
$content = substr_replace( $content, ' aria-describedby="emailHelp" ', $str_pos, 0 );
$str_pos2 = strpos( $content, 'name="your-fname-homepage"' );
$content = substr_replace( $content, ' aria-describedby="fnameHelp" ', $str_pos2, 0 );
$str_pos3 = strpos( $content, 'name="your-lname-homepage"' );
$content = substr_replace( $content, ' aria-describedby="lnameHelp" ', $str_pos3, 0 );
return $content;
}
Extending on from Tofandel's solution, for the benefit of those who got 99% of the way there, but suffered validation issues - I've resolved that in my case and would like to offer an extended solution that gets as far as Tofandel's (putting the attribute into the form proper) but also successfully validates on submission.
add_filter('wpcf7_form_tag', function($tag) {
$data = [];
foreach ((array)$tag['options'] as $option) {
if (strpos( $option, 'autocomplete') === 0) {
$option = explode(':', $option, 2);
$data[$option[0]] = apply_filters('wpcf7_option_value', $option[1], $option[0]);
}
}
if(!empty($data)) {
add_filter('wpcf7_form_elements', function ($content) use ($tag, $data) {
$data_attrs = wpcf7_format_atts($data);
$name = $tag['name'];
$content_plus_data_attrs = str_replace("name=\"$name\"", "name=\"$name\" " . $data_attrs, $content);
return $content_plus_data_attrs;
});
}
return $tag;
} );
Rather than changing the tag ID to a random value only to replace it with the "real" value later, we just reference the real value in the first place, replacing the relevant part of the content in the wpcf7_form_elements filter (in my case, autocomplete, but as Tofandel's example shows, this can be extended to any data attribute you'd like).
I propose a solution from the one given by Tofandel without JS (CF7) error and to authorize the use of an attribute without value:
/**
* Add custom attributes on inputs
* Put "data-my-attribute" to use it, with or without value
*
* #param array $tag
*
* #return array
*/
function cf7AddCustomAttributes($tag) {
$datas = [];
foreach ((array) $tag['options'] as $option) {
if (strpos($option, 'data-') === 0 || strpos($option, 'id:') === 0) {
$option = explode(':', $option, 2);
$datas[$option[0]] = apply_filters('wpcf7_option_value', $option[1], $option[0]);
}
}
if (!empty($datas)) {
$id = $tag['name'];
if (array_key_exists('id', $datas)) {
$id = $datas['id'];
} else {
$tag['options'][] = "id:$id";
}
add_filter('wpcf7_form_elements', function ($content) use ($id, $datas) {
$attributesHtml = '';
$idHtml = "id=\"$id\"";
foreach ($datas as $key => $value) {
$attributesHtml .= " $key";
if (is_string($value) && strlen($value) > 0) {
$attributesHtml .= "=\"$value\"";
}
}
return str_replace($idHtml, "$idHtml $attributesHtml ", $content);
});
}
return $tag;
}
add_filter('wpcf7_form_tag', 'cf7AddCustomAttributes');
I use this simple method for setting attribute
[checkbox optName use_label_element "optName"]
<script>
document.querySelector(".optName").setAttribute("onchange","myscript");
</script>
I have a category called 'News'. The category ID is '20'. I am using the Divi (Divi child) theme + Wordpress and want to shorten the excerpt for the News category.
I typically would use the 'add_filter' function like this:
<pre>
add_filter('excerpt_length', 'news_excerpt_length');
function news_excerpt_length($length) {
if(in_category(20)) {
return 30;
} else {
return 60;
}
}
</pre>
But that ain't workin'. I found the excerpt control in the 'main-modules.php' and figure to add my filter here? Has anyone done this?
I added the 'main-module.php' to the root of my child theme and then added this to my child 'functions.php'
<pre>
if ( ! function_exists( 'et_builder_add_main_elements' ) ) :
function et_builder_add_main_elements() {
require ET_BUILDER_DIR . 'main-structure-elements.php';
require 'main-modules.php';
do_action( 'et_builder_ready' );
}
endif;
</pre>
It didn't break the theme, but it didn't work either. Does anyone have any experience with this particular issue?
-Thanks!
To override the post_excerpt lengh, you can find in custom_functions.php the function truncate_post()
if ( ! function_exists( 'truncate_post' ) ) {
function truncate_post( $amount, $echo = true, $post = '', $strip_shortcodes = false ) {
global $shortname;
if ( '' == $post ) global $post;
$post_excerpt = '';
$post_excerpt = apply_filters( 'the_excerpt', $post->post_excerpt );
if ( 'on' == et_get_option( $shortname . '_use_excerpt' ) && '' != $post_excerpt ) {
if ( $echo ) echo $post_excerpt;
else return $post_excerpt;
} else {
// get the post content
$truncate = $post->post_content;
// remove caption shortcode from the post content
$truncate = preg_replace( '#\[caption[^\]]*?\].*?\[\/caption]#si', '', $truncate );
// remove post nav shortcode from the post content
$truncate = preg_replace( '#\[et_pb_post_nav[^\]]*?\].*?\[\/et_pb_post_nav]#si', '', $truncate );
// Remove audio shortcode from post content to prevent unwanted audio file on the excerpt
// due to unparsed audio shortcode
$truncate = preg_replace( '#\[audio[^\]]*?\].*?\[\/audio]#si', '', $truncate );
if ( $strip_shortcodes ) {
$truncate = et_strip_shortcodes( $truncate );
} else {
// apply content filters
$truncate = apply_filters( 'the_content', $truncate );
}
// decide if we need to append dots at the end of the string
if ( strlen( $truncate ) <= $amount ) {
$echo_out = '';
} else {
$echo_out = '...';
// $amount = $amount - 3;
}
// trim text to a certain number of characters, also remove spaces from the end of a string ( space counts as a character )
$truncate = rtrim( et_wp_trim_words( $truncate, $amount, '' ) );
// remove the last word to make sure we display all words correctly
if ( '' != $echo_out ) {
$new_words_array = (array) explode( ' ', $truncate );
array_pop( $new_words_array );
$truncate = implode( ' ', $new_words_array );
// append dots to the end of the string
$truncate .= $echo_out;
}
if ( $echo ) echo $truncate;
else return $truncate;
};
}
}
You don't need to put if ( ! function_exists( 'truncate_post' ) ) { to make it work just create your function with the same name in functions.php
If you are using a child theme (I really hope so with a theme like this), copy/paste index.php and paste these lines, line 54
if(in_category(20)) {
truncate_post( 30 );
} else {
truncate_post( 60 );
}
It can be easier
Hope it helps
I ended up doing it ( although I don't know which solution is better ) by putting this in my 'main-module.php' starting on line 12319
// do not display the content if it contains Blog, Post Slider, Fullwidth Post Slider, or Portfolio modules to avoid infinite loops
if ( ! has_shortcode( $post_content, 'et_pb_blog' ) && ! has_shortcode( $post_content, 'et_pb_portfolio' ) && ! has_shortcode( $post_content, 'et_pb_post_slider' ) && ! has_shortcode( $post_content, 'et_pb_fullwidth_post_slider' ) ) {
if ( 'on' === $show_content ) {
global $more;
// page builder doesn't support more tag, so display the_content() in case of post made with page builder
if ( et_pb_is_pagebuilder_used( get_the_ID() ) ) {
$more = 1;
the_content();
} else {
$more = null;
the_content( esc_html__( 'read more...', 'et_builder' ) );
}
} else {
if ( has_excerpt() ) {
the_excerpt();
} else {
if(in_category(20)) {
echo wpautop( truncate_post( 70, false ) );
} else {
echo wpautop( truncate_post( 370, false ) );
}
}
}
} else if ( has_excerpt() ) {
the_excerpt();
}
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.
Let me tell you the scenario first say the structure of the categories in wordpress is like this
Level 1: Top
Level 2: -Nextme_1
Level 3: --Nextme_2
--Nextme_3
Level 4: ---Nextme_4
---Nextme_5
Now I require to check what is the level of the category? Say I catch a category of level 3 so I have to use different template and if its level 4. Then I need to use another template?
Anybody can give me some hint?
Thanks
Rahul
If you don't have many categories you can try to edit their slug from admin, and then in your page you get the category slug this way:
if (is_category()) {
$cat = get_query_var('cat');
$category = get_category($cat);
echo 'your slug is '. $category->slug;
}
Now, when you're editing the categories slugs try naming them after their level: cat-lvl-1, cat-lvl-2. Then in your page you extract the number from category slug using some php string function, and then you check that number:
if ($category->slug == 1 ) {
//load the template for the category of level 1
}
if ($category->slug == 2 ) {
//load the template for the category of level 2
}
and so on.
Later edit:
Try this:
function get_level($category, $level = 0)
{
if ($category->category_parent == 0) {
return $level;
} else {
$level++;
$category = get_category($category->category_parent);
get_level($category, $level);
}
}
if (is_category()) {
$cat = get_query_var('cat');
$yourcat = get_category($cat);
echo get_level($yourcat);
}
You can call the get_ancestors() function to get an array containing the parents of the given object. Then you need to count elements in the result.
function get_the_level($id, $type = 'category') {
return count( get_ancestors($id, $type) );
}
if( is_category() ) {
$level = get_the_level( $cat );
}
elseif( is_product_category() ) {
$level = get_the_level( $wp_query->get_queried_object()->term_id, 'product_cat' );
}
Thanks a lot. This is superb with slight a change the code that you have written is fine but its not returning any value.(i,e the $level) although its calculating correct. A minor change i did and its work fine now with a slight editing of you code given below..
`
function get_level($category, $level = 0)
{
if ($category->category_parent == 0) {
return $level;
} else {
$level++;
$category = get_category($category->category_parent);
return get_level($category, $level);
}
}
if (is_category()) {
$cat = get_query_var('cat');
$yourcat = get_category($cat);
echo get_level($yourcat);
}
`
Thanks #zuzuleinen
I visited this page months back. I came back today, arrow up on the above solution then still went digging. Although it is a good solution, Wordpress often offers better or close.
get_category_parents()
This function does as Rahul has typed basically. It also calls itself which seems the most logical approach and that is why Rahul gets a point from me on this. Do not use $link, return a string of categories, explode() them then count or I suppose we could count the number of times the separator has been used and add 1.
function get_category_parents( $id, $link = false, $separator = '/', $nicename = false, $visited = array() ) {
$chain = '';
$parent = get_term( $id, 'category' );
if ( is_wp_error( $parent ) )
return $parent;
if ( $nicename )
$name = $parent->slug;
else
$name = $parent->name;
if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) {
$visited[] = $parent->parent;
$chain .= get_category_parents( $parent->parent, $link, $separator, $nicename, $visited );
}
if ( $link )
$chain .= ''.$name.'' . $separator;
else
$chain .= $name.$separator;
return $chain;
}