Wordpress: preg_replace inside a loop only works occasionally - php

I'm trying to make a custom RSS feed with some alteration to the HTML content of each post.
Inside the template file rss-custom.php I have this:
<?php while (have_posts()) : the_post(); ?>
<?php echo processPostContent(); ?>
<?php endwhile; ?>
in functions.php, there are three replacements as follows :
function processPostContent() {
$post = get_post(get_the_ID());
$post_content = strval($post->post_content);
// replace h3 and h4 tags with h2
$post_content = preg_replace('/<(\/?)h((?![12])\d)/im', "<$1h2", $post_content);
// strip every attribute of <img> other than src
$post_content = preg_replace('/<img[^>]*(src="[^"]*")[^>]*>/im', "<img $1 />", $post_content);
// insert text after some closing tags
$post_content = preg_replace('/<\/(h2|p|figure)>/im', "</$1><p>Inserted</p>", $post_content);
return $post_content;
}
Then I get a strange result: out of 20 posts, only 7-8 of them will have been fully replaced. The remaining get the first two replacements but not the third one. Does anyone know why that is?

The solution, turns out, doesn't have anything to do with the loop nor preg_replace. Some posts' contents do not include any HTML tag, only plain text. That's why preg_replace didn't have any effect on them. When those contents are rendered in the RSS feed, however, <p> tags are automatically inserted. That's what led me to believe the third replacement was skipped.
First paragraph.
Second paragraph.
is turned to
<p>First paragraph.</p>
<p>Second paragraph.</p>

Related

Remove the opening and closing div inside WordPress content

I want to remove a div added by a plugin to the content of WordPress posts. So the post has this structure:
<div class="post">
<div class="some-class">
<p>content</p>
</div>
</div>
I want to remove <div class="some-class"> and its closing </div> but leave the content. So it would be:
<div class="post">
<p>content</p>
</div>
using this filter:
add_filter( 'the_content', 'remove_class' , 100 );
function remove_class( $content ) {
$content = preg_replace('#<div[^>]*class="some-class"[^>]*>.*?</div>#is', '', $content);
return $content;
}
the content is also deleted, I just want the div and the closing div to be deleted. Any idea how?
this question is not duplicate of the other question because I want to remove a specific div not just all divs
You could just try to remove class attribute, so that only <div> is left, using code like this:
add_filter( 'the_content', 'remove_class' , 100 );
function remove_class( $content ) {
$content = preg_replace('/class=".*?"/', '', $content);
return $content;
}
#user7592255 you can try with jQuery like this:
$('p').unwrap();
If you can set an id or class on the p element you can target it more accurately
The content is removed because you replace the entire matched string with an empty string. Use a subpattern to capture the content of the <div> element and use it as replacement:
$content = preg_replace(
'#<div[^>]*class="some-class"[^>]*>(.*?)</div>#is',
'$1',
$content
);
However, be aware that it won't work properly if the content of <div class="some-class"> contains a <div> element.
There is no way to parse HTML using regex. The correct solution is to use an HTML parser (DOMDocument f.e.) to parse the HTML fragment and create its DOM, then operate the changes on the DOM and render it back to HTML.

putting paragraph tags on content paragraphs

Im trying to put paragraph text around the paragraphs. This code pulls out the blockquotes from my Wordpress post and outputs everything else
html
<?php
$block2 = get_the_content();
$block2 = preg_replace('~<blockquote>([\s\S]+?)</blockquote>~', '', $block2);
echo '<p>'.$block2.'</p>';
?>
But it only puts < p > tags around the fist paragraph and not the others
If I've understood this correctly, you could try splitting $block2 by newlines, looping through the resulting array and wrapping each element of the array in <p> tags as you have done.
Currently, your code wraps the entire content of $block2 in <p> tags, where I assume you wanted it to wrap the sections separated by newlines.
Example (I don't remember the exact syntax for PHP - sorry):
$split_block = split($block2, '\n');
for ($i in $split_block) {
$split_block[$i] = '<p>'.$split_block[$i].'</p>';
}
echo $split_block;

Wordpress retain formatting when calling extended content?

I am calling in content in Wordpress via the below code. Eseentially, I am dividing the content of the post into three sections; 1. Before the tag, 2. After the tag and 3. Post gallery. The code I have so far works perfectly to get the content, however I am having an issue as all formatting tags (p in particular) are being stripped. Is there a way to retain these?
Thanks
<?php
// Fetch post content
$content = get_post_field( 'post_content', get_the_ID() );
// Get content parts
$content_parts = get_extended( $content );
?>
<p>
<?php echo $content_parts['main']; // Output content before <!--more--> ?>
</p>
<p class="read-more">
<?php echo strip_shortcodes($content_parts['extended']); // Output content after <!--more--> ?>
</p>
<button>Read More</button>
<?php $gallery = get_post_gallery_images( $post ); ?>
When you pull the post content using get_post_field, the autop filter is not applied:
http://codex.wordpress.org/Function_Reference/wpautop
You can apply all of the content filters yourself by adding this line after you set $content:
$content = apply_filters('the_content', $content);

Using PHP is there a way to detect if there are two uninterrupted occurrences of an element?

This is a difficult question for me to word correctly, but I am trying to dynamically insert an ASIDE [specifically, just a "special thanks" note] between paragraphs. Initially I decided to drop this after the second paragraph by using substr_count(). I am floating this block, so if all it had to deal with was textual content there was no issue word-wrapping it. However, if it ran adjacent to an image or a PRE or anything else, it got wonky.
Anyway, what I want to do is detect when there is the first occurrence of TWO adjacent paragraphs and insert my aside between those. I.e.:
<p> Here is the first paragraph. </p>
<aside> INSERT THIS HERE </aside>
<p> Here is the second paragraph. </p>
Thoughts are appreciated.
Update: the substr_count() I am currently using.
Because I got voted down for not showing the original code, I'll post it below. I am using Wordpress but this isn't a WP specific question, as I'm taking the_content() as the string, counting the occurrences of P, and inserting the custom field there. This is ultimately not what I want to do, but I want to count two concurrent P's and insert this field between. It may be formatted strangely, as of course when I c/p from my editor stuff was all over the place.
$thanks = get_post_meta(get_the_ID(), 'thanks', true);
if (!$thanks) {
the_content();
}
else {
$show_after_p = 0;
$content = apply_filters('the_content', $post->post_content);
if(substr_count($content, '<p>') > $show_after_p) {
$contents = explode("</p>", $content);
$p_count = 0;
foreach($contents as $content)
{
echo $content;
if($p_count == $show_after_p)
{
?>
<aside class="thanks clearfix">
<p>
<?php echo '<span>Special thanks: </span>'.$thanks; ?>
</p>
</aside>
<?php }
echo "</p>";
$p_count++;
}
}
}
?>
Why not JS?
Well, javascript could definitely do this, but if I can do this in PHP then yahtzee.
use regular expression and preg_replace - search for: (closing of P){whitespaces (if any)}(opening P) and change whitespaces to your text.
something like that:
$content = preg_replace('#</p>\s*<p#', "</p><aside> INSERT THIS HERE </aside><p", $content);
Kudos to Jerzy Zawadzki for the inspiration. If you refer to the original code I segmented the content at the P tags using explode(). Now I am using preg_split() as follows:
$contents == preg_split('#</p>\s*<p>#', $content); // Thanks Jerzy
$i = 0;
foreach ( $contents as $content ) {
echo $content;
if ( $i == $show_after_p ) { // this is set to 0 right now
// insert aside here
}
echo "<p>";
$i++;
}
}
As far as I can tell, this busts up the content only at segments where there are concurrent paragraphs and no whitespace / images / other elements. At this first junction, I insert the aside. Then the content is appears as normal.

Remove HTML code from content printed by wordpress

I am printing out the content of a specific post (103 in this case) with the following code:
<?php $post_id = 103; $queried_post = get_post($post_id); echo apply_filters('the_content',$queried_post->post_content); ?>
How can I make it exclude all the html tags like <p> and <br>s, and just show the text?
Thanks!
Use strip_tag(string) function to remove all html tags from string
echo strip_tags(apply_filters('the_content',$queried_post->post_content));

Categories