I am writing a code for wordpress to separate paragraph using PHP. The objective is to split the content of the post into an array and echo them accordingly.
Here are my code
<?php
$content = "<p>123</p> <p>456</p> <p>789</p>"
$p = explode("</p>", $content);
$i=0;
//echo first 2 elements
foreach ($p as $para) {
echo $para;
array_shift($p); //remove the first element
$i++; //increase the element count by 1
if ($i == 2){ break;} //if element has reach 2 meaning second paragraph, stop loop.
}
echo "<br>Break here<br>";
//echo the rest of the element
foreach ($p as $para) {
echo $para;
}
?>
Replace this
$content = "<p>123</p> <p>456</p> <p>789</p>"
With the following
$content = apply_filters( 'the_content', get_the_content() );
$content = str_replace( ']]>', ']]>', $content );
to retrieve the content of the post with paragraph tag.
I am able to achieve my result but I am just worry of the consequences such as system overload.
If i understand correctly, what you're trying to accomplish, is adding a couple of <br> tags after the first two paragraphs?
If so, this can be done alot simpler using the preg_replace method:
$content = "<p>123</p> <p>456</p> <p>789</p>";
echo preg_replace('/<\/p>/', '</p><br><br>', $content, 2);
Related
I have previously built some html pages where several paragraphs are inside div and now i want to move it in WordPress to understand theming and the structure of the CMS but i have some issues to understand. For example, in the loop i can't just add the opening div at the starting point and the closing div at the end (obviously) because in the middle there are different elements wrapped in other div. For example, I wanted to take the last paragraph, create a wrapping div around it with a custom class and my solution was this. I am sure it is a totally messed up solution. What am I doing wrong?
// First function
function addDivLastP1( $content ) {
$pattern = '/[\s\S]*\K(<p>)/i';
// Here i adding the opening tag div. I close it later in another function
$replacement = '<div class="my_class">$1';
$content = preg_replace( $pattern, $replacement, $content );
return $content;
}
add_filter( 'the_content', 'addDivLastP1' );
// Second function
function addDivLastP2( $content ) {
$pattern = '/[\s\S]*\K(<\/p>)/i';
// Closing div previously open
$replacement = '</div>';
$content = preg_replace( $pattern, $replacement, $content );
return $content;
}
add_filter( 'the_content', 'addDivLastP2' );
It is not a good idea to parse HTML (or any XML) by regexp.
In your case much better use DOMDocument:
function addDivLastP( $content ) {
$doc = new DOMDocument();
if(!$doc->loadHTML($content)) {
// cannot parse HTML content
return $content;
}
for($i = $doc->childNodes->count()-1; $i >= 0; $i--) {
$child = $doc->childNodes[$i];
if ($child->nodeName === 'p') { // got last paragraph inside root node
$div = $doc->createElement('div');
// replace paragraph by new empty div
$doc->replaceChild($div, $child);
// insert paragraph inside div
$div->appendChild($child);
return $doc->saveHTML();
}
}
return $content;
}
I want to put just the first paragraph of my posts on my index.php
in my functions.php I have
<?php
{
global $post;
$output = get_the_content();
$wanted_number_of_paragraph = 1;
$tmp = explode ('</p>', $output);
for ($i = 0; $i < $wanted_number_of_paragraph; ++$i) {
if (isset($tmp[$i]) && $tmp[$i] != '') {
$tmp_to_add[$i] = $tmp[$i];
}
}
$output = implode('</p>', $tmp_to_add) . '</p>';
echo $output;
}
?>
then in my index.php
<?php wpden_excerpt(); ?>
However it posts the entire post (including pictures) and not just the first paragraph.
I wold recommend you to use the Wordpress get_extended() function for this purpose. In your post you split the content with the "more" tag, after inside your template you can have something like:
global $post;
// gets the content of your post as an array of 2 parts
$content_parts = get_extended( $post->post_content );
and after this you can echo the part before the "more" tag like:
<?=$content_parts['main'];?>
the part after the "more" tag you can echo like:
<?=$content_parts['extended'];?>
Also, if you chose this option I'll recommend you to check the wpautop() , since you may need to wrap these 2 parts with it, for example:
<?=wpautop($content_parts['extended']);?>
Preface: i am not a good coder.
I need to use $post->post_content to get the raw post so that i can use the EXPLODE php command. But when i do use $post->post_content, it filters out the tags that are in my post which need to be retained. here is my script. what am i doing wrong? thanks!
<?php
$content = apply_filters('the_content', $post->post_content);
$contents = array_filter(explode("</p>", $content));
foreach ($contents as $content) {
if (strpos($content, '<img') !== false ) {
echo $content;
echo "</p>after image ad";
} else {
echo $content;
echo "</p>";
}
}
?>
I'm basically trying to insert an Ad after any paragraph that only contains an image.
It seems that when you call:
$content = apply_filters('the_content', $post->post_content);
It applies autop to split the paragraphs, and also applies do_shortcode on all shortcodes.
So you'd better not to call apply_filters here, but call wpautop instead:
See: http://codex.wordpress.org/Function_Reference/wpautop
<?php
$content = wpautop( $post->post_content );
$contents = array_filter(explode("</p>", $content));
$result = '';
foreach ($contents as $content) {
$result .= $content.'</p>';
if (strpos($content, '<img') !== false ) {
$result .= "after image ad";
}
}
$content = apply_filters('the_content', $result);
echo $result;
?>
Though this is Wordpress orientated, I think the basis of the PHP is more a Stackoverflow question:
I would like to add a template_part (similar to include()) before the first <p> in a post.
I can't add the template_part before the_content() because inside the the_content() is sometimes a <figure> then <p>:
<figure>....</figure>
// Want to insert here!
<p>.......</p>
<p>.......</p>
<p>.......</p>
<figure>....</figure>
<p>.......</p>
<p>.......</p>
These are the two codes I have tried using, but not sure how to make it go before the first <p>:
Method one:
$after = 1;
$content = apply_filters('the_content', $post->post_content);
if(substr_count($content, '<p>') > $after) {
$contents = explode("</p>", $content); $p_count = 0;
foreach($contents as $content){
echo $content; if($p_count == $after){
get_template_part('path/to/part');
} $p_count++;
}
}
Method two:
$paragraphAfter[1] = get_template_part('path/to/part');
$content = apply_filters( 'the_content', get_the_content() );
$content = explode("</p>", $content);
$count = count($content);
for ($i = 0; $i < $count; $i++ ) {
if ( array_key_exists($i, $paragraphAfter) ) {
echo $paragraphAfter[$i];
}
echo $content[$i] . "</p>";
}
Preferably the more efficient method, either from above or your own :]
A dirty hack could be:
function add_the_string_filter( $content ) {
$string_to_append = 'your string to add';
$content = preg_replace('/<p>/', $string_to_append . '<p>', $content , 1);
return $content;
}
add_filter( 'the_content', 'add_the_string_filter' );
The last parameter of the preg_replace is the limit, which tells to replace only the first occurence.
Is it possible to filter out only the shortcode from the post and then run the shortcode?
My page looks like this:
[summary img="images/latest.jpg"]
This here is the summary
[/summary]
Lots of text here...
And i just want to display the shortcode on a specific page.
Tried using regular expressions, but they dont seem to work:
$the_query = new WP_Query('category_name=projects&showposts=1');
//loop
while ( $the_query->have_posts() ) : $the_query->the_post();
echo '<b>';
the_title();
echo '</b>';
echo '<p>';
$string = get_the_content();
if (preg_match("[\\[[a-zA-Z]+\\][a-zA-Z ]*\\[\/[a-zA-Z]+\\]]", $string , $matches)) {
echo "Match was found <br />";
echo $matches[0];
}
echo '</p>';
endwhile;
Any idéas?
EDIT:
Found a temporary solution.
while ( $the_query->have_posts() ) : $the_query->the_post();
$content = str_replace(strip_shortcodes(get_the_content()),"",get_the_content());
echo do_shortcode($content);
endwhile;
I saw that wordpress had a function for striping shortcodes but not for strip content. So i replaced the stripped content string from the whole post to get just the shortcode. The only bad thing about this that the shortcodes have to be in the beginning of the posts.
Better answer is:
$pattern = get_shortcode_regex();
preg_match('/'.$pattern.'/s', $post->post_content, $matches);
if (is_array($matches) && $matches[2] == 'the_shortcode_name') {
$shortcode = $matches[0];
echo do_shortcode($shortcode);
}
It will search through the post content for a shortcode called “the_shortcode_name”. If it finds it, it will store the shortcode in the $matches variable. Easy to run it from there.
I've had the following problems with these answers:
regex pattern not containing all registered shortcode tags
inability to get all shortcodes from the post
.. and my solution is:
// Return all shortcodes from the post
function _get_shortcodes( $the_content ) {
$shortcode = "";
$pattern = get_shortcode_regex();
preg_match_all('/'.$pattern.'/uis', $the_content, $matches);
for ( $i=0; $i < 40; $i++ ) {
if ( isset( $matches[0][$i] ) ) {
$shortcode .= $matches[0][$i];
}
}
return $shortcode;
}
Use it like so:
<?php echo do_shortcode( _get_shortcodes( get_the_content() ) ) ?>
Search wherever your shortcode position is on your content
Example :
[my_shortcode]
[my_shortcode_2]
or
[my_shortcode_2]
[my_shortcode]
Functions.php
function get_shortcode($code,$content) {
$pattern = get_shortcode_regex();
preg_match_all('/'.$pattern.'/s',$content,$matches);
if(is_array($matches) && isset($matches[2]) && in_array($code,$matches[2])) {
$index = array_search($code,$matches[2]);
$shortcode = $matches[0][$index];;
return do_shortcode($shortcode);
} else {
return false;
}
}
Using example :
$content = $post->post_content;
$my_shortcode = get_shortcode('my_shortcode',$content);
$my_shortcode_2 = get_shortcode('my_shortcode_2',$content);
echo $my_shortcode;
if($my_shortcode){ // if shortcode#1 found so echo shortcode#2 after
echo $my_shortcode_2;
}
use this regex
preg_match('/\[summary[^\]]*](.*)\[\/summary[^\]]*]/uis', $string , $matches)
$match[1] should be your text
Edit: ok to match any combination of tags
use
/\[([^\]]+)\](.*?)\[\/\1\]/uis
but if you have nested tags you might need to parse the matches again recursively. However if it is a wordpress free text i think you might get too complex cases that a simple script can handle
You can do this using the get_shortcode_regex() function to get the regex for all registered shotcodes in your blog, apply that to the content to get an array of shortcodes found in that content, then call the appropriate callback to process the one you want.
So inside a loop somewhere it would be something like:
$pattern = get_shortcode_regex();
$matches = array();
preg_match_all("/$pattern/s", get_the_content(), $matches);
var_dump($matches); //Nested array of matches
//Do the first shortcode
echo preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $matches[0][0] );
This will execute the first shortcode found in the post, obviously in practice you want to check that you've got one!