I am using the following code below to output content from a category, but the content has bold tags which in turn makes my entire sold bold. What would be easiest way to remove the bold text in my code? Any help would be greatly appreciated, as I am using this to learn.
<p><?php $content = get_the_content();
if (mb_strlen($content) > 700) {
$content = mb_substr($content, 0, 700);
// make sure it ends in a word by chomping at last space
$content = mb_substr($content, 0, mb_strrpos($content, " ")).'...<br /><span class="landing_latest_articles_read_more">Read More</span>';
}
echo $content; ?></p>
strip_tags
or this might work
$string = preg_replace("/<b>|</b>/", "", $string);
Here is a function like strip_tags, only it removes only the tags (with attributes) specified:
<?php
function strip_only($str, $tags) {
if(!is_array($tags)) {
$tags = (strpos($str, '>') !== false ? explode('>', str_replace('<', '', $tags)) : array($tags));
if(end($tags) == '') array_pop($tags);
}
foreach($tags as $tag) $str = preg_replace('#</?'.$tag.'[^>]*>#is', '', $str);
return $str;
}
?>
so you will use it like this
<p><?php $content = get_the_content();
if (mb_strlen($content) > 700) {
$content = mb_substr($content, 0, 700);
// make sure it ends in a word by chomping at last space
$content = mb_substr($content, 0, mb_strrpos($content, " ")).'...<br /><span class="landing_latest_articles_read_more">Read More</span>';
$content = strip_only($content, '<b>'); //you want to remove <b> tag
}
echo $content; ?></p>
This is working. i tried it here.
If you only wish to remove bold tags:
$content = preg_replace('/<[\/]?b>/i', '', $content);
^
Though you'd have to be sure that it is only <b> tags making things bold and not font tags.
Related
I have some code that outputs a title and a description for a list of posts. I am trying to limit the length of text for both. The title is $story->title, and outputs just fine. However the description, represented by $story->excerpt in the code, contains html tags in the database. The limit_text function seems to strip these tags from the text. I think I need to limit the characters differently or need a function to allow those tags to work.
I have tried some functions that allows the tags to be seen but not function properly. But I am new to php in general so I don't know many functions.
<?php
foreach($stories as $story) {
echo '<h2>'.limit_text($story->title, 80).'</h2>';
if(!empty($story->excerpt)) {
echo '<p>'.limit_text($story->excerpt, 150).'</p>';
} else {
echo limit_text($story->body, 150);
}
}
?>
I found the function for limit_text
function limit_text($string, $limit = 140) {
$string = preg_replace('/<figcaption>.*?<\/figcaption>/','',$string);
$string = preg_replace('/<div class=\"wp_image_caption\">.*?<\/div>/','',$string);
$string = str_replace(' ','',$string);
$string = substr($string, strpos($string, "<p><strong>"));
$string = strip_tags($string);
$string = substr($string, 0, $limit);
$string = $string.'...';
return $string;
}
The reason why my tags were being stripped was the strip_tagsmethod right in the function. Duh. Hehe. Thanks for the comments.
Try this limit text function instead
public function limitText($text, $len)
{
$text = preg_match('#<\s*?b\b[^>]*>(.*?)</b\b[^>]*>#s', $text, $matches);
return "<b>" . substr($text,0, $len) . "</b>";
}
I have this sample code:
<?php
$string='Left text from tag <div title="hello world" class="CSS">What is <b>going on</b> here?<br> Calm up <em>right now</em>.</div> Right text. Possible another <div title="" class="DD">tag..</div> but not always.';
echo strip_tags($string);
?>
The result of this code is:
Left text from tag What is going on here? Calm up right now. Right text. Possible another tag.. but not always.
However, my goal is to REMOVE all text (including tags) between the tags removed by this strip_tags function. Ie. the result should be:
Left text from tag Right text. Possible another but not always.
I know it can be done with preg_replace, but it's too slow so maybe there is a faster solution.. (not necessarily related to strip_tags function).
Using REGEX is the best and most compact solution in my opinion. Try this:
echo preg_replace('#<(\w+)\b.*?>.*?</\1>#si', '', $string);
If you don't want to use preg_replace, use the customized function strip_tags_content() mentioned in the manual.
function strip_tags_content($text, $tags = '', $invert = FALSE) {
preg_match_all('/<(.+?)[\s]*\/?[\s]*>/si', trim($tags), $tags);
$tags = array_unique($tags[1]);
if(is_array($tags) AND count($tags) > 0) {
if($invert == FALSE) {
return preg_replace('#<(?!(?:'. implode('|', $tags) .')\b)(\w+)\b.*?>.*?</\1>#si', '', $text);
} else {
return preg_replace('#<('. implode('|', $tags) .')\b.*?>.*?</\1>#si', '', $text);
}
} elseif($invert == FALSE) {
return preg_replace('#<(\w+)\b.*?>.*?</\1>#si', '', $text);
}
return $text;
}
echo strip_tags_content($string);
Note: I don't think yor desired output could be achieved using PHP functions only. You need to use REGEX in one way or the other.
How about a DOMDocument approach?
<?php
$string='Left text from tag <div title="hello world" class="CSS">What is <b>going on</b> here?<br> Calm up <em>right now</em>.</div> Right text. Possible another <div title="" class="DD">tag..</div> but not always.';
$dom = new DomDocument();
$dom->loadHTML('<body>' . $string . '</body>');
$stripped = '';
$els = $dom->getElementsByTagName('body')->item(0)->childNodes;
$len = count($els) - 1;
foreach($els as $index => $child) {
if (is_null($child->tagName))
$stripped .= ' ' . trim($child->nodeValue);
}
$stripped = substr($stripped, 1);
echo $stripped;
Output:
Left text from tag Right text. Possible another but not always.
I'm using the buffer sanitizer, as seen in a PHP manual comment, but having trouble with double newlines in textareas.
When pulling a string out from my database, containing double/triple/quadruple newlines, and putting it into a textarea, the newlines are reduced to only a single newline.
Therefore: Is it possible to have the function exclude all output between <pre>, <textarea> and </pre>, </textarea>?
Seeing this question, How to minify php html output without removing IE conditional comments?, I think i need to use the preg_match, but I'm not sure how to implement it into this function.
The function I'm using is
function sanitize_output($buffer) {
$search = array(
'/\>[^\S ]+/s', // strip whitespaces after tags, except space
'/[^\S ]+\</s', // strip whitespaces before tags, except space
'/(\s)+/s' // shorten multiple whitespace sequences
);
$replace = array(
'>',
'<',
'\\1'
);
$buffer = preg_replace($search, $replace, $buffer);
return $buffer;
}
ob_start("sanitize_output");
And yeah I'm using both this sanitizer and GZIP to get the smallest size possible.
here is an implementation of the function mentioned in the comments:
function sanitize_output($buffer) {
// Searching textarea and pre
preg_match_all('#\<textarea.*\>.*\<\/textarea\>#Uis', $buffer, $foundTxt);
preg_match_all('#\<pre.*\>.*\<\/pre\>#Uis', $buffer, $foundPre);
// replacing both with <textarea>$index</textarea> / <pre>$index</pre>
$buffer = str_replace($foundTxt[0], array_map(function($el){ return '<textarea>'.$el.'</textarea>'; }, array_keys($foundTxt[0])), $buffer);
$buffer = str_replace($foundPre[0], array_map(function($el){ return '<pre>'.$el.'</pre>'; }, array_keys($foundPre[0])), $buffer);
// your stuff
$search = array(
'/\>[^\S ]+/s', // strip whitespaces after tags, except space
'/[^\S ]+\</s', // strip whitespaces before tags, except space
'/(\s)+/s' // shorten multiple whitespace sequences
);
$replace = array(
'>',
'<',
'\\1'
);
$buffer = preg_replace($search, $replace, $buffer);
// Replacing back with content
$buffer = str_replace(array_map(function($el){ return '<textarea>'.$el.'</textarea>'; }, array_keys($foundTxt[0])), $foundTxt[0], $buffer);
$buffer = str_replace(array_map(function($el){ return '<pre>'.$el.'</pre>'; }, array_keys($foundPre[0])), $foundPre[0], $buffer);
return $buffer;
}
There is always room for optimation but that works
There is a simple solution for PRE that does not work for TEXTAREA: replace the spaces with then use nl2br() to replace the newlines with BR elements before outputting the values. It's not elegant but it works:
<pre><?php
echo(nl2br(str_replace(' ', ' ', htmlspecialchars($value))));
?></pre>
Unfortunately, it cannot be used for TEXTAREA because the browsers display <br /> as text.
Maybe this will give you the result you need.
But in general i do not recommend this kind of sanitize jobs, it's not good for performance. In these days there is no really need of stripping whitespace characters from a html output.
function sanitize_output($buffer) {
$ignoreTags = array("textarea", "pre");
# find tags that must be ignored and replace it with a placeholder
$tmpReplacements = array();
foreach($ignoreTags as $tag){
preg_match_all("~<$tag.*?>.*?</$tag>~is", $buffer, $match);
if($match && $match[0]){
foreach($match[0] as $key => $value){
if(!isset($tmpReplacements[$tag])) $tmpReplacements[$tag] = array();
$index = count($tmpReplacements[$tag]);
$replacementValue = "<tmp-replacement>$index</tmp-relacement>";
$tmpReplacements[$tag][$index] = array($value, $replacementValue);
$buffer = str_replace($value, $replacementValue, $buffer);
}
}
}
$search = array(
'/\>[^\S ]+/s', // strip whitespaces after tags, except space
'/[^\S ]+\</s', // strip whitespaces before tags, except space
'/(\s)+/s' // shorten multiple whitespace sequences
);
$replace = array(
'>',
'<',
'\\1'
);
$buffer = preg_replace($search, $replace, $buffer);
# re-insert previously ignored tags
foreach($tmpReplacements as $tag => $rows){
foreach($rows as $values){
$buffer = str_replace($values[1], $values[0], $buffer);
}
}
return $buffer;
}
function nl2ascii($str){
return str_replace(array("\n","\r"), array("
","
"), $str);
}
$StrTest = "test\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\rtest";
ob_start("sanitize_output");
?>
<textarea><?php echo nl2ascii($StrTest); ?></textarea>
<textarea><?php echo $StrTest; ?></textarea>
<pre style="border: 1px solid red"><?php echo nl2ascii($StrTest); ?></pre>
<pre style="border: 1px solid red"><?php echo $StrTest; ?></pre>
<?php
ob_flush();
raw output
<textarea>test
test</textarea>
<textarea>test
test</textarea>
<pre style="border: 1px solid red">test
test</pre>
<pre style="border: 1px solid red">test
test</pre>
visual output
This is my version of the sanitize HTML. I have commented the code, so it should be clear what it is doing.
function comprimeer($html = '', $arr_tags = ['textarea', 'pre']) {
$arr_found = [];
$arr_back = [];
$arr_temp = [];
// foreach tag get an array with tag and its content
// the array is like: $arr_temp[0] = [ 0 = ['<tag>content</tag>'] ];
foreach ($arr_tags as $tag) {
if(preg_match_all('#\<' . $tag . '.*\>.*\<\/' . $tag . '\>#Uis', $html, $arr_temp)) {
// the tag is present
foreach($arr_temp as $key => $arr_item) {
// for every item of the tag keep the item
$arr_found[$tag][] = $arr_item[0];
// make an nmubered replace <tag>1</tag>
$arr_back[$tag][] = '<' . $tag . '>' . $key . '</' . $tag . '>';
}
// replace all the present tags with the numbered ones
$html = str_replace((array) $arr_found[$tag], (array) $arr_back[$tag], $html);
}
} // end foreach
// clean the html
$arr_search = [
'/\>[^\S ]+/s', // strip whitespaces after tags, except space
'/[^\S ]+\</s', // strip whitespaces before tags, except space
'/(\s)+/s' // shorten multiple whitespace sequences
];
$arr_replace = [
'>',
'<',
'\\1'
];
$clean = preg_replace($arr_search, $arr_replace, $html);
// put the kept items back
foreach ($arr_tags as $tag) {
if(isset($arr_found[$tag])) {
// the tag was present replace them back
$clean = str_replace($arr_back[$tag], $arr_found[$tag], $clean);
}
} // end foreach
// give the cleaned html back
return $clean;
} // end function
I have a problem using the below:
<?php echo excerpt(15); ?>
Because! I have some pages (unfortunately) that have on-page styles and little text, not meeting the 15 characters, so what is occurring is the excerpt limit is not being met, so it displays 'a little text.. then <css> <styles><h1> <h2>, etc'.
How can I re-write as UP to 15 character limit, or MAX. So if it falls short that's fine. Or to exclude HTML / and CSS?
Excerpt function within functions.php
function excerpt($limit) {
$excerpt = explode(' ', get_the_excerpt(), $limit);
if (count($excerpt)>=$limit) {
array_pop($excerpt);
$excerpt = implode(" ",$excerpt).'...';
} else {
$excerpt = implode(" ",$excerpt);
}
$excerpt = preg_replace('`\[[^\]]*\]`','',$excerpt);
return $excerpt;
}
function content($limit) {
$content = explode(' ', get_the_content(), $limit);
if (count($content)>=$limit) {
array_pop($content);
$content = implode(" ",$content).'...';
} else {
$content = implode(" ",$content);
}
$content = preg_replace('/\[.+\]/','', $content);
$content = apply_filters('the_content', $content);
$content = str_replace(']]>', ']]>', $content);
return $content;
}
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'custom_trim_excerpt');
function custom_trim_excerpt($text) { // Fakes an excerpt if needed
global $post;
if ( '' == $text ) {
$text = get_the_content('');
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]>', $text);
$text = strip_tags($text);
$excerpt_length = 35;
$words = explode(' ', $text, $excerpt_length + 1);
if (count($words) > $excerpt_length) {
array_pop($words);
array_push($words, '...');
$text = implode(' ', $words);
}
}
return $text;
}
You have three options (possibly more, this isn't meant to be exhaustive)
Abandon the wordpress function. By using custom PHP passing the $post->post_content through to your own function you could use PHP's XML manipulation functions, specifically DOM manipulation, or a regular expression to remove certain tags.
Do a check on your post content before running excerpt. If you can check for the existence of a tag to start within the first 15 characters by checking for the first position of a "<" character using strpos, then you can use a normal if/else.
Using wordpresses functionality properly, you can change how the excerpt is dealt with through filters. You can remove the default functionality and replace it with your own. This link in particular is very useful for explaining how to customise your excerpt function in wordpress, specifically with regards to allowing tags or not within the excerpt.
$text = "<p>keep me</p> <p>strip me </p>
$pattern = "/<[^\/>]*>(\ \;)*<\/[^>]*>/";
$text = preg_replace($pattern, '', $text);
Hi, I need to strip "quasi-empty" p tags from a html string. there's always only a as a trigger in the p element. how can I strip it with regex?
The following pattern will match all <p> </p> blocks that include along with any accompanying text, as per your example.
$text = "<p>keep me</p> <p>strip me </p>";
$pattern = "/<p>[^<]* \;[^<]*<\/p>/";
$output = preg_replace($pattern, '', $text);
If you actually want it to only strip out <p> </p> blocks with and spaces, use the following pattern instead:
$pattern = "/<p>(\s* \;\s*)+<\/p>/";
If you want to only strip out <p> </p> blocks that have an and up to a certain number of characters, use the following (setting the $maxChars variables as you see fit):
$maxCharsBefore = 10;
$maxCharsAfter = 10;
$pattern = "/<p>[^<]{0,".$maxCharsBefore."} \;[^<]{0,".$maxCharsAfter."}<\/p>/";
$text = preg_replace("!<p>(?: )*</p>!", "", $text);
$text = "<p>keep me</p> <p>strip me </p>";
str_replace(' ','',$text);
job done
Yo have a lot of learning to do: http://www.regular-expressions.info/conditional.html
<?php
$text = "<p>keep me</p> <p>strip me </p><div class=\"someclass\">div</div>";
$newtext = "";
preg_match_all("/(\<.*?>.*?<\/.*?>)/",$text,$matches);
foreach($matches[0] as $tag)
{
if(!strstr($tag,' '))
{
$newtext .= $tag;
}
}
echo $newtext;
?>