I need a split string with 2 divs, by the first div with 20 words and last div with rest of words to make read more link with javascript.
At the moment I have only character count limit.
How can I do word splitting?
if ( $term && ! empty( $term->description ) ) {
$first = substr($term->description, 0, 400);
$rest = substr($term->description, 400);
echo '<div class="term-description"><div class="first-letter">'.$first.'</div><div class="last-letter">'.$rest.'</div></div>';
}
This code does the trick:
<?php
function SplitStringToParts($sourceInput, &$first, &$rest, $countWordsInFirst = 20)
{
$arr_exploded = explode(" ", $sourceInput);
$arr_part1 = array_slice($arr_exploded, 0, $countWordsInFirst);
$arr_part2 = array_slice($arr_exploded, $countWordsInFirst);
$first = implode(" ",$arr_part1);
$rest = implode(" ",$arr_part2);
}
$str = "str1 str2 str3 str4 str5 str6 str7 str8 str9 str10 str11 str12 str13 str14 str15 str16 str17 str18 str19 str20 str21 str22 str23 str24";
SplitStringToParts($str,$first,$rest,20);
echo $first."<br>";
echo $rest."<br>";
Output is:
str1 str2 str3 str4 str5 str6 str7 str8 str9 str10 str11 str12 str13 str14 str15 str16 str17 str18 str19 str20
str21 str22 str23 str24
Use SplitStringToParts function. In your case you should call it as:
SplitStringToParts($term->description, $first, $rest, 20);
After it $first, $rest will keep your result
Found solution:
<?php
// sentence teaser
// this function will cut the string by how many words you want
function word_teaser($string, $count){
$original_string = $string;
$words = explode(' ', $original_string);
if (count($words) > $count){
$words = array_slice($words, 0, $count);
$string = implode(' ', $words);
}
return $string;
}
// sentence reveal teaser
// this function will get the remaining words
function word_teaser_end($string, $count){
$words = explode(' ', $string);
$words = array_slice($words, $count);
$string = implode(' ', $words);
return $string;
}
?>
$string = "We are BrightCherry web design, and we're going to show you how to write a function to crop a string by a certain amount of words."
//this will echo the first 10 words of the string
echo word_teaser($string, 10);
$string = "We are BrightCherry web design, and we're going to show you how to write a function to crop a string by a certain amount of words."
//this will echo the words after the first 10 words
echo word_teaser_end($string, 10);
Related
I have a search String: $str (Something like "test"), a wrap string: $wrap (Something like "|") and a text string: $text (Something like "This is a test Text").
$str is 1 Time in $text. What i want now is a function that will wrap $str with the wrap defined in $wrap and output the modified text (even if $str is more than one time in $text).
But it shall not output the whole text but just 1-2 of the words before $str and then 1-2 of the words after $str and "..." (Only if it isn`t the first or last word). Also it should be case insensitive.
Example:
$str = "Text"
$wrap = "<span>|</span>"
$text = "This is a really long Text where the word Text appears about 3 times Text"
Output would be:
"...long <span>Text</span> where...word <span>Text</span> appears...times <span>Text</span>"
My Code (Obviusly doesnt works):
$tempar = preg_split("/$str/i", $text);
if (count($tempar) <= 2) {
$result = "... ".substr($tempar[0], -7).$wrap.substr($tempar[1], 7)." ...";
} else {
$amount = substr_count($text, $str);
for ($i = 0; $i < $amount; $i++) {
$result = $result.".. ".substr($tempar[$i], -7).$wrap.substr($tempar[$i+1], 0, 7)." ..";
}
}
If you have a tipp or a solution dont hesitate to let me know.
I have taken your approach and made it more flexible. If $str or $wrap changes you could have escaping issues within the regex pattern so I have used preg_quote.
Note that I added $placeholder to make it clearer, but you can use $placeholder = "|" if you don't like [placeholder].
function wrapInString($str, $text, $element = 'span') {
$placeholder = "[placeholder]"; // The string that will be replaced by $str
$wrap = "<{$element}>{$placeholder}</{$element}>"; // Dynamic string that can handle more than just span
$strExp = preg_quote($str, '/');
$matches = [];
$matchCount = preg_match_all("/(\w+\s+)?(\w+\s+)?({$strExp})(\s+\w+)?(\s+\w+)?/i", $text, $matches);
$response = '';
for ($i = 0; $i < $matchCount; $i++) {
if (strlen($matches[1][$i])) {
$response .= '...';
}
if (strlen($matches[2][$i])) {
$response .= $matches[2][$i];
}
$response .= str_replace($placeholder, $matches[3][$i], $wrap);
if (strlen($matches[4][$i])) {
$response .= $matches[4][$i];
}
if (strlen($matches[5][$i]) && $i == $matchCount - 1) {
$response .= '...';
}
}
return $response;
}
$text = "text This is a really long Text where the word Text appears about 3 times Text";
string(107) "<span>text</span> This...long <span>text</span> where...<span>text</span> appears...times <span>text</span>"
To make the replacement case insensitive you can use the i regex option.
If I understand your question correct, just a little bit of implode and explode magic needed
$text = "This is a really long Text where the word Text appears about 3 times Text";
$arr = explode("Text", $text);
print_r(implode('<span>Text</span>', $arr));
If you specifically need to render the span tags using HTML, just write it that way
$arr = explode("Text", $text);
print_r(implode('<span>Text</span>', $arr));
Use patern below to get your word and 1-2 words before and after
/((\w+\s+){1,2}|^)text((\s+\w+){1,2}|$)/i
demo
In PHP code it can be:
$str = "Text";
$wrap = "<span>|</span>";
$text = "This is a really long Text where the word Text appears about 3 times Text";
$temp = str_replace('|', $str, $wrap); // <span>Text</span>
// find patern and 1-2 words before and after
// (to make it casesensitive, delete 'i' from patern)
if(preg_match_all('/((\w+\s+){1,2}|^)text((\s+\w+){1,2}|$)/i', $text, $match)) {
$res = array_map(function($x) use($str, $temp) { return '... '.str_replace($str, $temp, $x) . ' ...';}, $match[0]);
echo implode(' ', $res);
}
I tried most of solution answered here but all of them have same problem which is my question here.
I use this function for highligh search results:
function highlightWords($searchtext, $searchstrings){
$searchstrings = preg_replace('/\s+/', ' ', trim($searchstrings));
$words = explode(' ', $searchstrings);
$highlighted = array();
foreach ( $words as $word ){
$highlighted[] = "<font color='#00f'><b>".$word."</b></font>";
}
return str_replace($words, $highlighted, $searchtext);
}
Problem occurs when i search text with 2 or more strings separated with spaces and any of them have any of HTML code from my highlighted array.
For example, searchtext="I have max system performance" AND searchstrings="max f"
In first iteration foreach will replace every max with <font color='#00f'><b>max</b></font>
In second iteration it will replace every f with <font color='#00f'><b>f</b></font>
Second iteration will also replace html tags inserted in first replacement!
So it will replace f in string <font color='#00f'> also?
Any suggestion?
Thanks
Miodrag
<?php
$searchtext = "I have max system performance";
$searchstrings = "max f";
$searchstrings = preg_replace('/\s+/', ' ', trim($searchstrings));
$words = explode(' ', $searchstrings);
$highlighted = array();
foreach ( $words as $word ){
$highlighted[] = "<font color='#00f'><b>".$word."</b></font>";
}
echo strtr($searchtext, array_combine($words, $highlighted));
?>
Maybe this is good Solution for you?
function highlightWords($searchtext, $searchstrings){
$searchstrings = preg_replace('/\s+/', ' ', trim($searchstrings));
$words = explode(' ', $searchstrings);
$highlighted = array();
foreach ( $words as $word ){
$highlighted[] = '<span class="highlighted-word">'.$word.'</span>';
}
return str_replace($words, $highlighted, $searchtext);
}
echo highlightWords('I have max system performance', 'max f');
?>
You need to add a little bit CSS on your Page:
<style>
.highlighted-word {
font-weight: bold;
}
</style>
Outputs:
I have max system performance
---
UPDATE:
If you like to hightlight the complete word, look at this:
function highlightCompleteWords($searchtext, $searchstrings){
$searchstrings = preg_replace('/\s+/', ' ', trim($searchstrings));
$words = explode(' ', $searchstrings);
$highlighted = array();
foreach ( $words as $word ){
$searchtext = preg_replace("/\w*?".preg_quote($word)."\w*/i", "<span class='highlighted-word'>$0</span>", $searchtext);
}
return $searchtext;
}
echo highlightCompleteWords('I have max system performance', 'max f');
Outputs: I have max system performance
I might not fully understand your question, but I guess you want to highlight every matched word in the search string.
You could probably just do something like:
$returnString = $searchtext;
foreach ( $words as $word ){
$returnString = preg_replace('/\b'.$word.'\b/i', "<font color='#00f'><b>$0</b></font>", $returnString);
}
return $returnString;
This would output: "I have max system performance"
Since the "f" wouldn't get matched
EDIT - This is if you wanna match part of a word as well.
Kind of ugly but I believe this will fork for you
$returnString = $searchtext;
foreach ( $words as $word ){
if(strlen($word)>2){
$returnString = preg_replace('/'.$word.'/i', "§§§$0###", $returnString);
}
}
$returnString = preg_replace("/\§§§/","<font color='#00f'><b>", $returnString);
$returnString = preg_replace("/\###/","</b></font>", $returnString);
return $returnString;
Try the following
foreach ( $words as $word ){
if(strlen ($word)>2)
{
$highlighted[] = "<font color='#00f'><b>".$word."</b></font>";
}
}
I am trying to use a script to search a text file and return words that meet certain criteria:
*The word is only listed once
*They are not one words in an ignore list
*they are the top 10% of the longest words
*they are not repeating letters
*The final list would be a random ten that met the above criteria.
*If any of the above were false then words reported would be null.
I've put together the following but the script dies at arsort() saying it expects an array. Can anyone suggest a change to make arsort work? Or suggest an alternative (simpler) script to find metadata?**I realize this second question may be a question better suited for another StackExchange.
<?php
$fn="../story_link";
$str=readfile($fn);
function top_words($str, $limit=10, $ignore=""){
if(!$ignore) $ignore = "the of to and a in for is The that on said with be was by";
$ignore_arr = explode(" ", $ignore);
$str = trim($str);
$str = preg_replace("#[&].{2,7}[;]#sim", " ", $str);
$str = preg_replace("#[()°^!\"§\$%&/{(\[)\]=}?´`,;.:\-_\#'~+*]#", " ", $str);
$str = preg_replace("#\s+#sim", " ", $str);
$arraw = explode(" ", $str);
foreach($arraw as $v){
$v = trim($v);
if(strlen($v)<3 || in_array($v, $ignore_arr)) continue;
$arr[$v]++;
}
arsort($arr);
return array_keys( array_slice($arr, 0, $limit) );
}
$meta_keywords = implode(", ", top_words( strip_tags( $html_content ) ) );
?>
The problem is when your loop never increments $arr[$v], which results in the possibility of $arr not becoming defined. This is the reason for your error because then arsort() is given null as its argument - not an array.
The solution is to define $arr as an array before the loop for instances where $arr[$v]++; isn't executed.
function top_words($str, $limit=10, $ignore=""){
if(!$ignore) $ignore = "the of to and a in for is The that on said with be was by";
$ignore_arr = explode(" ", $ignore);
$str = trim($str);
$str = preg_replace("#[&].{2,7}[;]#sim", " ", $str);
$str = preg_replace("#[()°^!\"§\$%&/{(\[)\]=}?´`,;.:\-_\#'~+*]#", " ", $str);
$str = preg_replace("#\s+#sim", " ", $str);
$arraw = explode(" ", $str);
$arr = array(); // Defined $arr here.
foreach($arraw as $v){
$v = trim($v);
if(strlen($v)<3 || in_array($v, $ignore_arr)) continue;
$arr[$v]++;
}
arsort($arr);
return array_keys( array_slice($arr, 0, $limit) );
}
Came across an excellent code that words well for this:
<?php
function extract_keywords($str, $minWordLen = 3, $minWordOccurrences = 2, $asArray = false, $maxWords = 5, $restrict = true)
{
$str = str_replace(array("?","!",";","(",")",":","[","]"), " ", $str);
$str = str_replace(array("\n","\r"," "), " ", $str);
strtolower($str);
function keyword_count_sort($first, $sec)
{
return $sec[1] - $first[1];
}
$str = preg_replace('/[^\p{L}0-9 ]/', ' ', $str);
$str = trim(preg_replace('/\s+/', ' ', $str));
$words = explode(' ', $str);
// If we don't restrict tag usage, we'll remove common words from array
if ($restrict == false) {
$commonWords = array('a','able','about','above', 'get a list here http://www.wordfrequency.info','you\'ve','z','zero');
$words = array_udiff($words, $commonWords,'strcasecmp');
}
// Restrict Keywords based on values in the $allowedWords array
// Use if you want to limit available tags
if ($restrict == true) {
$allowedWords = array('engine','boeing','electrical','pneumatic','ice','pressurisation');
$words = array_uintersect($words, $allowedWords,'strcasecmp');
}
$keywords = array();
while(($c_word = array_shift($words)) !== null)
{
if(strlen($c_word) < $minWordLen) continue;
$c_word = strtolower($c_word);
if(array_key_exists($c_word, $keywords)) $keywords[$c_word][1]++;
else $keywords[$c_word] = array($c_word, 1);
}
usort($keywords, 'keyword_count_sort');
$final_keywords = array();
foreach($keywords as $keyword_det)
{
if($keyword_det[1] < $minWordOccurrences) break;
array_push($final_keywords, $keyword_det[0]);
}
$final_keywords = array_slice($final_keywords, 0, $maxWords);
return $asArray ? $final_keywords : implode(', ', $final_keywords);
}
$text = "Many systems that traditionally had a reliance on the pneumatic system have been transitioned to the electrical architecture. They include engine start, API start, wing ice protection, hydraulic pumps and cabin pressurisation. The only remaining bleed system on the 787 is the anti-ice system for the engine inlets. In fact, Boeing claims that the move to electrical systems has reduced the load on engines (from pneumatic hungry systems) by up to 35 percent (not unlike today’s electrically power flight simulators that use 20% of the electricity consumed by the older hydraulically actuated flight sims).";
echo extract_keywords($text);
// Advanced Usage
// $exampletext = "The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog.";
// echo extract_keywords($exampletext, 3, 1, false, 5, false);
?>
I am trying to test if a string made up of multiple words and has any values from an array at the end of it. The following is what I have so far. I am stuck on how to check if the string is longer than the array value being tested and that it is present at the end of the string.
$words = trim(preg_replace('/\s+/',' ', $string));
$words = explode(' ', $words);
$words = count($words);
if ($words > 2) {
// Check if $string ends with any of the following
$test_array = array();
$test_array[0] = 'Wizard';
$test_array[1] = 'Wizard?';
$test_array[2] = '/Wizard';
$test_array[4] = '/Wizard?';
// Stuck here
if ($string is longer than $test_array and $test_array is found at the end of the string) {
Do stuff;
}
}
By end of string do you mean the very last word? You could use preg_match
preg_match('~/?Wizard\??$~', $string, $matches);
echo "<pre>".print_r($matches, true)."</pre>";
I think you want something like this:
if (preg_match('/\/?Wizard\??$/', $string)) { // ...
If it has to be an arbitrary array (and not the one containing the 'wizard' strings you provided in your question), you could construct the regex dynamically:
$words = array('wizard', 'test');
foreach ($words as &$word) {
$word = preg_quote($word, '/');
}
$regex = '/(' . implode('|', $words) . ')$/';
if (preg_match($regex, $string)) { // ends with 'wizard' or 'test'
Is this what you want (no guarantee for correctness, couldn't test)?
foreach( $test_array as $testString ) {
$searchLength = strlen( $testString );
$sourceLength = strlen( $string );
if( $sourceLength <= $searchLength && substr( $string, $sourceLength - $searchLength ) == $testString ) {
// ...
}
}
I wonder if some regular expression wouldn't make more sense here.
Does anybody have the exact name of the function Drupal uses to turn the following string:
"Hello, how are you. Some more text."
into
"Hello, how..."
I.e. The function that's used to cut off a sentence after x words, and then add an elipsis. Alternatively, if anybody has a php snippet that does this, that would be great too!
function getFirstWords($string, $words = 1)
{
$string = explode(' ', $string);
if (count($string) > $words)
{
return implode(' ', array_slice($string, 0, $words)) . '...';
}
return implode(' ', $string);
}
echo getFirstWords('Hello, how are you. Some more text.', 2); // Hello, how...
It seems to be truncate_utf8() in unicode.inc.
You can use function views_trim_text($alter, $value)
view more detail https://api.drupal.org/api/views/views.module/function/views_trim_text/7
$alter['html'] = TRUE;
$alter['max_length'] = 200;
$alter['word_boundary'] = TRUE;
$alter['ellipsis'] = TRUE;
print views_trim_text($alter, $output);