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!
Related
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);
Here the problem:
I have two div #post-playlist-list and post-playlist-description
I want to use two shortcodes [texte-article] and [playlist-article]
I need a function which get all the content between[texte-article][/texte-article] to put in #post-playlist-list
and another function which get the [playlist-article][/playlist-article] content into #post-playlist-description
I began to learn at preg_replace but the syntax is not that easy to learn.
I you can help me on this, it would be great.
Ok i tried the function i don't have error but it doesn't seems to return anything
Don't i need to escape the second ] ion the Regexp? like "/[texte-article](.*)[/texte-article]/"
Here's the code in my single.php :
<div id="post-playlist-list" class="box">
<?php
$id = get_the_ID();
$post = get_post($id);
$content = apply_filters('the_content', $post->post_content);
$content = str_replace( ']]>', ']]>', $content );
echo $content;
?>
</div>
<div id="post-playlist-description" >
<?php
echo $content;
?>
</div>
Here's the code in my single.php:
function texte_article_function() {
preg_replace_callback("/\[texte-article\](.*)\[\/texte-article\]/", function($matches) {
//$matches contains an array of all matches
//$matches[0] stores the full pattern match: \[texte-article](.*)\[\/texte-article]
//$matches[1] stores the first subpattern match: (.*)
//Do whatever text parsing you need to do here and return the result.
$content = $matches[0];
return $content;
}, $postdata);
}
function playlist_article_function() {
preg_replace_callback("/\[playlist-article\](.*)\[\/playlist-article\]/", function($matches) {
//$matches contains an array of all matches
//$matches[0] stores the full pattern match: \[texte-article](.*)\[\/texte-article]
//$matches[1] stores the first subpattern match: (.*)
//Do whatever text parsing you need to do here and return the result.
$content = $matches[0];
return $content;
}, $postdata);
}
function register_shortcodes(){
add_shortcode('texte-article', 'texte_article_function');
add_shortcode('playlist-article', 'playlist_article_function');
}
add_action( 'init', 'register_shortcodes');
Thanks for all the answers :) here's the solution, using regex:
functions.php
function texte_article_function($content_texte_article) {
//Get [texte-article] content
$content_texte_article = preg_replace('#.*\[texte-article\](.*)\[\/texte-article\].*#s', '$1', $content_texte_article);
return $content_texte_article;
}
function playlist_article_function($content_playlist_article) {
//get [fap_playlist] content
$content_playlist_article = preg_replace('#.*\[playlist-article\](.*)\[\/playlist-article\].*#s', '$1', $content_playlist_article);
return $content_playlist_article;
}
Callback functions:
<?php
$id = get_the_ID();
$post = get_post($id);
$content_playlist_article = $content;
$btn_play_index_id = $content;
echo playlist_article_function($content_playlist_article);
// echo $content;
?>
<?php
$content_texte_article = $content;
echo texte_article_function($content_texte_article);
?>
If it can help someone.
I am trying yo understand this function, as a preface to forking it to make similar functions for my own shortcodes. I understand how to define shortcodes and their functions. I also basically "get" what the original author is doing here: collecting parameters from the shortcode and assembling them into an HTML tag and returning that tag. It seems the order of the params is unimportant, but their names are.
However, when I am working with this code, it does not seem to understand which param is which. For example, the original docs say to use the shortcode like so:
[button link="http://google.com" color="black" size="small"]Button Text[/button]
But when I use this shortcode, I get:
<a href="Button Text" title="Array" class="button button-small button " target="_self">
<span>Array</span>
</a>
Here's my PHP:
if( ! function_exists( 'make_button' ) ) {
function make_button( $text, $url, $color = 'default', $target = '_self', $size = 'small', $classes = null, $title = null ) {
if( $target == 'lightbox' ) {
$lightbox = ' rel="lightbox"';
$target = null;
} else {
$lightbox = null;
$target = ' target="'.$target.'"';
}
if( ! $title )
$title = $text;
$output = '<a href="'.$url.'" title="'.$title.'" class="button button-'.$size.' '.$color.' '.$classes.'"'.$target.$lightbox.'>';
$output .= '<span>'.$text.'</span>';
$output .= '</a>';
return $output;
}
}
add_shortcode( 'button', 'make_button' );
See the documentation for Shortcode API, there clearly states that three parameters are passed to the shortcode callback function:
$atts - an associative array of attributes, or an empty string if no
attributes are given
$content - the enclosed content (if the shortcode is used in its enclosing form)
$tag - the shortcode tag, useful for shared callback functions
So the function definition should look like:
function make_button( $atts, $content, $tag ) {
// use print_r to examine attributes
print_r($atts);
}
The shortcode is explicitly looking for $text.
[button url="http://google.com" color="black" size="small" text="Button Text"]
Typically the variable that is set when you use the open/close shortcode is $content, per the Shortcode API. Another fix would be to change the shortcode to look for $content instead of $text.
I have the following function in my theme's function page. basically what it does is look for any image in the post page and add some spans with css to dynamically create a pinterest button.
function insert_pinterest($content) {
global $post;
$posturl = urlencode(get_permalink()); //Get the post URL
$pinspan = '<span class="pinterest-button">';
$pinurlNew = '<a href="#" onclick="window.open("http://pinterest.com/pin/create/button/?url='.$posturl.'&media=';
$pindescription = '&description='.urlencode(get_the_title());
$options = '","Pinterest","scrollbars=no,menubar=no,width=600,height=380,resizable=yes,toolbar=no,location=no,status=no';
$pinfinish = '");return false;" class="pin-it"></a>';
$pinend = '</span>';
$pattern = '/<img(.*?)src="(.*?).(bmp|gif|jpeg|jpg|png)"(.*?) \/>/i';
$replacement = $pinspan.$pinurlNew.'$2.$3'.$pindescription.$options.$pinfinish.'<img$1src="$2.$3" $4 />'.$pinend;
$content = preg_replace( $pattern, $replacement, $content );
//Fix the link problem
$newpattern = '/<a(.*?)><span class="pinterest-button"><a(.*?)><\/a><img(.*?)\/><\/span><\/a>/i';
$replacement = '<span class="pinterest-button"><a$2></a><a$1><img$3\/></a></span>';
$content = preg_replace( $newpattern, $replacement, $content );
return $content;
}
add_filter( 'the_content', 'insert_pinterest' );
it does everything just fine. but is there a way to have it skip over an image with a certain class name in it like "noPin" ?
I would use preg_replace_callback to check if a matched image contains noPin.
function skipNoPin($matches){
if ( strpos($matches[0], "noPin") === false){
return $pinspan.$pinurlNew.'$matches[2].$matches[3]'.$pindescription.$options.$pinfinish.'<img$1src="$2.$3" $4 />'.$pinend;
} else {
return $matches[0]
$content = preg_replace_callback(
$pattern,
skipNoPin,
$content );
Another image attribute could conceivably contain noPin, if you are concerned about that edge case, just make the test in the if statement more specific.
You have to exclude the class noPin from the $pattern regexp :
$pattern = '/<img(.*?)src="(.*?).(bmp|gif|jpeg|jpg|png)"(.*?) \/>/i';
Has to become something like
$pattern = '/<img(.*?)src="(.*?).(bmp|gif|jpeg|jpg|png)"(.*?) (?!class="noPin") \/>/i';
Please check the regexp syntax, but the idea is to exclude class="noPin" from the searched pattern. Then your replacement will not be added to these images.
I'm still pinned against wordpress it seems. I added the widget 'Archives' to my sidebar and once more, the html output is crap, it basically has this structure:
<li>text - (# of posts)</li>
I want to transform it into:
<li>text <small># of posts</small>
Unlike with plugins however, I wasn't able to find the line that creates the html output in the php pages suggested/mentioned by the wordpress community, namely functions.php, widgets.php and default-widgets.php
I've googled every possible keyword combination on the matter and I was unable to find something relevant.
All help is appreciated
Regards
G.Campos
Check out general-template.php. Two functions wp_get_archives and get_archives_link. You'd have to hack wp_get_archives to change what gets loaded in $text. The post count gets loaded into the $after variable which placed outside the link in get_archives_link. Instead of this:
$text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($arcresult->month), $arcresult->year);
if ( $show_post_count )
$after = ' ('.$arcresult->posts.')' . $afterafter;
something like this:
$text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($arcresult->month), $arcresult->year);
if ( $show_post_count )
$text= $text.' <small>'.$arcresult->posts.'</small>';
That's just for the Monthly archive. You'd have to make modifications on the Yearly, Weekly and Daily blocks.
Edit: Easiest way to exclude the <small> element from the link's title is to load it up in a separate variable in each block and then pass it into a modified get_archives_link. In the example above, right after $text gets loaded up just load that value into $title:
$text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($arcresult->month), $arcresult->year);
$title = $text;
if ( $show_post_count )
$text= $text.' <small>'.$arcresult->posts.'</small>';
$output .= get_archives_link($url, $text, $format, $before, $after, $title);
Then modify get_archives_link:
function get_archives_link($url, $text, $format = 'html', $before = '', $after = '', $title = '') {
$text = wptexturize($text);
if($title == '')
$title = $text;
$title_text = esc_attr($title);
$url = esc_url($url);
if ('link' == $format)
$link_html = "\t<link rel='archives' title='$title_text' href='$url' />\n";
elseif ('option' == $format)
$link_html = "\t<option value='$url'>$before $text $after</option>\n";
elseif ('html' == $format)
$link_html = "\t<li>$before<a href='$url' title='$title_text'>$text</a>$after</li>\n";
else // custom
$link_html = "\t$before<a href='$url' title='$title_text'>$text</a>$after\n";
$link_html = apply_filters( "get_archives_link", $link_html );
return $link_html;
}
Add this code inside your theme functions.php file, It will wrap post archive counts inside span tag. In below code example I wrapped counts in span tag, you can add or modify it according to your requirement.
function wrap_archive_count($links) {
$links = str_replace('</a> (', '<span class="archive-count">', $links);
$links = str_replace(')', '</span></a>', $links);
return $links;
}
add_filter('get_archives_link', 'wrap_archive_count');