I can't seem to get the wpv-contains to work.
My site hosts a list of articles and books. Each one is accompanied by an abstract (article) or publisher's note (book). Sometimes the string 'Abstract' or 'Publisher's Note' appears at the beginning of a record (post body), but other times it does not - that's just how the records are imported. Rather than going through hundreds of records to add the missing words, I want to build a nested conditional which will:
1. look if the post body contains 'Abstract' or 'Publisher's Note'
2. if it does contain either of those, print nothing
3. if it does not contain either of those, check the content of a custom field 'medium'
4. if it equals 1 (book), print 'Publisher's Note'
5. if it equals 2 (article), print 'Abstract'
Here is what I have
[wpv-conditional if="(wpv_contains('[types field='wpv-post-body' output='raw'][/types]','Abstract' OR 'Publisher's Note') eq false )"]
[wpv-conditional if="( $(wpcf-medium) eq '1' )"]Publisher's Note: [/wpv-conditional]
[wpv-conditional if="( $(wpcf-medium) eq '2' )"]Abstract: [/wpv-conditional]
[/wpv-conditional]
[wpv-post-body view_template="None" output="raw"]
The inner conditionals which display 'Abstract' or 'Publisher Note' depending on medium type, work fine. But the first one doesn't.
Naturally, I have added the wpv_contains function in the Toolset settings, and the code to my theme's functions.php:
function wpv_contains($haystack, $needle)
{
$pos = strpos($haystack, $needle);
if($pos !== true){
return false;
}
}
Can you let me know what I am doing wrong?
Hi,
Thank you for contacting us and I'd be happy to assist.
The post's content can't be accessed using the "types" shortcode which works for the custom fields, which is why this shortcode is not correct: [types field='wpv-post-body' output='raw'][/types]
To get the post's content, you can use the "wpv-post-body" shortcode for example:
[wpv-post-body view_template="None" output="raw"]
( ref: https://toolset.com/documentation/programmer-reference/views/views-shortcodes/#wpv-post-body )
I couldn't make your custom function work on my test website, but, you can simplify the conditional evaluations by registering a custom shortcode that can check if the desired text (needle) is available in the post's body or not and return 1 or 0, respectively.
For example:
add_shortcode('body_text_contains', 'body_text_contains_func');
function body_text_contains_func($atts) {
$a = shortcode_atts( array(
'needle' => '',
), $atts );
$content = do_shortcode("[wpv-post-body view_template='None' suppress_filters='true']");
$pos = strpos($content, $a['needle']);
if($pos >= 1){
return '1';
}
else
{
return '0';
}
}
Next, please add "body_text_contains" in the "Third-party shortcode arguments" section, at WP Admin -> Toolset -> Settings -> Front-end Content.
Example usage in conditional statements:
[wpv-conditional if="( '[body_text_contains needle="Abstract"]' eq '1' ) OR ( '[body_text_contains needle="Publisher's Note"]' eq '1' )" debug="true"]
One of the two strings is found!
[/wpv-conditional]
I hope this helps and for more personalized assistance around custom code, you can also consider hiring a professional from our list of recommended contractors:
https://toolset.com/contractors/
regards,
Waqar
Thanks!
I followed the advice and it certainly did something! Now each of the records displays the following text at the point where the code is:
####################
wpv-conditional attributes
####################
Array
(
[if] => ( '0' = '0' ) OR ( '1' = '0' ) OR ( '0' = '0' ) OR ( '0' = '0' ) OR ( '0
[debug] => true
)
####################
Debug information
####################
--------------------
Original expression: ( '0' = '0' ) OR ( '1' = '0' ) OR ( '0' = '0' ) OR ( '0' = '0' ) OR ( '0
--------------------
After replacing 1 general variables and comparing strings: ( 0 = 0 ) OR ( '1' = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 ) OR ( '0
Comparing 0 to 0
After replacing 2 general variables and comparing strings: ( 0 = 0 ) OR ( 1 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 ) OR ( '0
Comparing 1 to 0
After replacing 3 general variables and comparing strings: ( 0 = 0 ) OR ( 1 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 ) OR ( '0
Comparing 0 to 0
After replacing 4 general variables and comparing strings: ( 0 = 0 ) OR ( 1 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 ) OR ( '0
Comparing 0 to 0
In the functions.php, I copied and pasted what you wrote
In the View, I have the following now:
[wpv-conditional if="( '[body_text_contains needle="Abstract:"]' eq '0' ) OR ( '[body_text_contains needle="Note:"]' eq '0' ) OR ( '[body_text_contains needle="Matter:"]' eq '0' ) OR ( '[body_text_contains needle="Syllabi:"]' eq '0' ) OR ( '[body_text_contains needle="Introduction:"]" debug="true"][wpv-conditional if="( $(wpcf-medium) eq '1' )"]Publisher's Note: [/wpv-conditional][wpv-conditional if="( $(wpcf-medium) eq '2' ) OR ( $(wpcf-medium) eq '3' ) OR ( $(wpcf-medium) eq '4' )"]Abstract: [/wpv-conditional][/wpv-conditional]
Note that Toolset is highlighting everything after needle="Abstract: in red, as if the closing " was the problem.
Thanks for writing back.
In the conditional block that you shared, a closing parenthesis was missing and you can replace inner double quotes with single quotes, so that editor can interpret the conditions correctly:
[wpv-conditional if="( '[body_text_contains needle='Abstract:']' eq '0' ) OR ( '[body_text_contains needle='Note:']' eq '0' ) OR ( '[body_text_contains needle='Matter:']' eq '0' ) OR ( '[body_text_contains needle='Syllabi:']' eq '0' ) OR ( '[body_text_contains needle='Introduction:']' eq '0' )" debug="true"]
[wpv-conditional if="( $(wpcf-medium) eq '1' )"]
Publisher's Note:
[/wpv-conditional]
[wpv-conditional if="( $(wpcf-medium) eq '2' ) OR ( $(wpcf-medium) eq '3' ) OR ( $(wpcf-medium) eq '4' )"]
Abstract:
[/wpv-conditional]
[/wpv-conditional]
The above block works on my test website.
Thank you!
Alas, the content template now still adds the words where it shouldn't. See example in the image, and debug info below. Apparently it displays it even if 1=0:
####################
wpv-conditional attributes
####################
Array
(
[if] => ( '0' = '0' ) OR ( '1' = '0' ) OR ( '0' = '0' ) OR ( '0' = '0' ) OR ( '0' = '0' )
[debug] => true
)
####################
Debug information
####################
--------------------
Original expression: ( '0' = '0' ) OR ( '1' = '0' ) OR ( '0' = '0' ) OR ( '0' = '0' ) OR ( '0' = '0' )
--------------------
After replacing 1 general variables and comparing strings: ( 0 = 0 ) OR ( '1' = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 )
Comparing 0 to 0
After replacing 2 general variables and comparing strings: ( 0 = 0 ) OR ( 1 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 )
Comparing 1 to 0
After replacing 3 general variables and comparing strings: ( 0 = 0 ) OR ( 1 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 )
Comparing 0 to 0
After replacing 4 general variables and comparing strings: ( 0 = 0 ) OR ( 1 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 )
Comparing 0 to 0
After replacing 5 general variables and comparing strings: ( 0 = 0 ) OR ( 1 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 ) OR ( 0 = 0 )
Comparing 0 to 0
Thanks for the update.
If your plan is to show the content from the parent conditional statement, only when none of the words are found, then the inner statements should be joined by "AND" and not by "OR":
[wpv-conditional if="( '[body_text_contains needle='Abstract:']' eq '0' ) AND ( '[body_text_contains needle='Note:']' eq '0' ) AND ( '[body_text_contains needle='Matter:']' eq '0' ) AND ( '[body_text_contains needle='Syllabi:']' eq '0' ) AND ( '[body_text_contains needle='Introduction:']' eq '0' )" debug="true"]
[wpv-conditional if="( $(wpcf-medium) eq '1' )"]
Publisher's Note:
[/wpv-conditional]
[wpv-conditional if="( $(wpcf-medium) eq '2' ) OR ( $(wpcf-medium) eq '3' ) OR ( $(wpcf-medium) eq '4' )"]
Abstract:
[/wpv-conditional]
[/wpv-conditional]
Ah, silly mistake, of course. Thank you! It works now.
Just one minor thing is not right - I keep getting a paragraph tag auto-inserted in the post body now.
I would like it to display:
Abstract: text here
But what it displays is:
Abstract:
text here
I even inlined everything in the content template editor to make sure some random break isn't interpreted as a new paragraph, but it didn't help at all. How to make this go away?
Here is the inlined code:
<p>[wpv-conditional if="( '[body_text_contains needle='Abstract:']' eq '0' ) AND ( '[body_text_contains needle='Note:']' eq '0' ) AND ( '[body_text_contains needle='Matter:']' eq '0' ) AND ( '[body_text_contains needle='Syllabi:']' eq '0' ) AND ( '[body_text_contains needle='Introduction:']' eq '0' )"][wpv-conditional if="( $(wpcf-medium) eq '1' )"]<strong>Publisher's Note:</strong>[/wpv-conditional][wpv-conditional if="( $(wpcf-medium) eq '2' ) OR ( $(wpcf-medium) eq '3' ) OR ( $(wpcf-medium) eq '4' )"]<strong>Abstract:</strong>[/wpv-conditional][/wpv-conditional]<span class="article-comment">[wpv-post-body view_template="None" suppress_filters="true" output="raw"]</span>
Here is the same not inlined:
<p>[wpv-conditional if="( '[body_text_contains needle='Abstract:']' eq '0' ) AND ( '[body_text_contains needle='Note:']' eq '0' ) AND ( '[body_text_contains needle='Matter:']' eq '0' ) AND ( '[body_text_contains needle='Syllabi:']' eq '0' ) AND ( '[body_text_contains needle='Introduction:']' eq '0' )"]
[wpv-conditional if="( $(wpcf-medium) eq '1' )"]
<strong>Publisher's Note:</strong>
[/wpv-conditional]
[wpv-conditional if="( $(wpcf-medium) eq '2' ) OR ( $(wpcf-medium) eq '3' ) OR ( $(wpcf-medium) eq '4' )"]
<strong>Abstract:</strong>
[/wpv-conditional]
[/wpv-conditional]
<span class="article-comment">
[wpv-post-body view_template="None" suppress_filters="true" output="raw"]
</span>
And this is what I get in the page inspector:
<div class="article-abstract">
<p><strong>Abstract:</strong>
<span class="article-comment">
</span>
</p>
<p>post body text here</p>
</div>
So basically, the code says that the post body should display within the article-comment span, but instead it displays in a separate paragraph behind it. Why?
Glad that it worked.
To make the bold text show in the same line as the rest of the body text, you can add a special class 'inline-txt' to it:
<strong class="inline-txt">Abstract:</strong>
And include some custom CSS code, in the template:
.inline-txt {float: left;}
.article-abstract {clear: both;}
That sounds like an odd hack and it produces weird results. Rather than adjusting the classes, wouldn't it be better to just ensure that the unnecessary <p> tags don't get added?
Removing the extra p tags can be challenging depending on the active theme and the third-party plugins activated on the website.
Can you please share a link to an example page where this conditional block can be seen?
( I have the admin access details from your other ticket )
Thank you for looking into it! Here is an example page: hidden link . You need to unfold the records using the dropdown arrow.
You'll notice the first record (Wiseman) on the list looks as it should - that's because the word 'Abstract:' is just written in post body (and so the conditional doesn't trigger).
The second and third (Dhanda, Khader) do not have the word in the body, so the conditional does trigger adding the words. But then it also adds the <p>
Thank you for sharing these details.
I managed to remove the extra p tags by removing the two opening p tags from the start of the conditional blocks.
( they were not closed anyway )
The challenge here is that the content coming from the post body/content already has the p tag and we can't insert our injected headings inside that p tag.
This is why, you'll have to include some CSS code to make the heading and the text appear to be inline.
.article-abstract strong,
.article-abstract p {
display:inline;
}
.article-abstract hr {
background: transparent;
margin-bottom: 0.5 em;
}
I also added an hr tag between the two conditional blocks, so that the content can have proper spacing.
Screenshot: hidden link
Thank you! I modified the solution a little, because sometimes I had abstracts or comments that had more than one paragraph and your solution was inlining those paragraphs as well:
.article-abstract p:first-of-type {
display:inline
}
.article-abstract p:nth-of-type(2) {
margin-top:1em
}
Thank you again for your help!