How to highlight changes/difference in one text paragraph from the other? - php

Is it possible to highlight the modifications in one text paragraph from the other?
For example, there are 3 text fields in a database. Non-admin users can edit the text and submit for approval. When the admin logs in, (s)he can open the approvals page and it shows the original text and user submitted text with modifications. Usually these modifications are very small in nature, like spelling correction or just a deletion or addition of a sentence.
Can it be presented in such a way that the modifications (from the original text) are highlighted so that admin users don't have to check every field and every line before they approve it?
Any help would be appreciated.
Thanks.
Updated:
Somewhat similar to TortoiseSVN's code changes highlighting.

Options:
PHP Inline Diff (uses PEAR text-diff)
PEAR Text_Diff
Diff in Pure PHP
xdiff_string_diff()
Stackoverflow Archive:
Highlight the difference between two strings in PHP
Apply Diff in PHP
Need Help Optimizing php string difference function

If you are familiar with GNU/Linux tools, you might be familiar with the `diff' tool.
And someone has written a fully functional diff for comparing files/strings in php.
You can find it here: php diff example.

This is an old thread but thought I'd catalog my findings.
If you want to use raw php, this is by far the simplest, fastest, and most effective solution I've found: http://paulbutler.org/archives/a-simple-diff-algorithm-in-php/
From what I can tell, the author of the above code is using an algorithm outlined in this article: http://www.codeproject.com/Articles/6943/A-Generic-Reusable-Diff-Algorithm-in-C-II
Basic description of what's happening (taken from the article):
Find the current Longest Matching Sequence (LMS) of items.
Store this LMS in a results pile.
Process all data left above the LMS using recursion.
Process all data left below the LMS using recursion.
Works like a charm!

Not sure, why these long solutions are there.
here I had found an easy one for me.
string1 = "The quick brown fox jumps over the lazy dog.";
$string2 = "The quick brown albino fox jumps the groovy dog.";
$string1 = explode(" ", $string1);
$string2 = explode(" ", $string2);
$diff = array_intersect($string2, $string1);
$tmp = array();
foreach ($string2 as $k => $w) {
if ($diff[$k]==$w) {
$tmp[$k] = $w;
}
else {
$tmp[$k] = "<b>$w</b>";
}
}
$diff = array_diff($string1, $tmp);
foreach ($diff as $k => $w) {
$tmp[$k] .= " [<strike>$w</strike>]";
}
echo join (' ', $tmp);
ref. https://forums.phpfreaks.com/topic/6525-how-do-i-highlight-differences-between-strings/

Related

How to get Sentence From Long String which contains specific Word using PHP

I know How to check if a string contains a specific word
if (str_contains('How are you', 'are')) {
echo 'true';
}
But I am looking for give search result like below to my users
so if my string is like below
Paragraph development begins with the formulation of the controlling
idea. This idea directs the paragraph’s development. Often, the
controlling idea of a paragraph will appear in the form of a topic
sentence. In some cases, you may need more than one sentence to
express a paragraph’s controlling idea.
and then if my user search with word like idea directs then I want show result like This idea directs the paragraph’s development
I do not have idea which PHP function can help me for achieve my goal. Let me know if anyone here can help me for achieve my goal. Thanks!
There is no simple function to achieve this directly. You will have to write an algorithm to get it done. Something similar below.
$text = "Paragraph development begins with the formulation of the controlling idea. This idea directs the paragraph’s development. Often, the controlling idea of a paragraph will appear in the form of a topic sentence. In some cases, you may need more than one sentence to express a paragraph’s controlling idea.";
$search = "idea directs";
$sentenses = explode(".", $text);
for($i = 0; i < sizeof($sentenses); $i++){
if(strpos($sentenses[$i], $search))
echo $sentenses[$i];
}
convert the text into lowercase will help you to search case-insensitive,

Ordering and Selecting frequently used tags

I have looked on stackoverflow for a solution to this however couldn't find a good answers which outlined the issues I was having; Essentially what I'm trying to achieve is to array out 15 of the most frequent tags used from all my users subjects.
This is how I currently select the data
$sql = mysql_query("SELECT subject FROM `users`");
$row = mysql_fetch_array($sql);
I do apologise for the code looking nothing like what I'm trying to achieve I really don't have any clue where to begin with trying to achieve this and came here for a possible solution. Now this would work fine and I'd be able to array them out and however my problem is the subjects contain words along with the hash tags so an example room subject would look like hey my name is example #follow me how would I only grab the #followand once I've grabbed all the hashtags from all of the subjects to echo the most frequent 15?
Again I apologise for the code looking nothing like what I'm trying to achieve and I appreciate anyone's help. This was the closest post I found to solving my issue however was not useful.
Example
Here is three room subjects;
`Hello welcome to my room #awesome #wishlist`
`Hey hows everyone doing? #friday #awesome`
`Check out my #wishlist looking #awesome`
This is what I'm trying to view them as
[3] #awesome [2] #wishlist [1] #friday
What you want to achieve here is pretty complex for an SQL query and you are likely to run in to efficiency problems with parsing the subject every time you want to run this code.
The best solution is probably to have a table that associates tags with users. You can update this table every time a user changes their subject. To get the number of times a tag is used then becomes trivial with COUNT(DISTINCT tag).
One way would be to parse the result set in PHP. Once you query your subject line from the database, let's say you have them in the array $results, then you can build a frequency distribution of words like this:
$freqDist = [];
foreach($results as $row)
{
$words = explode(" ", $row);
foreach($words as $w)
{
if (array_key_exists($w, $freqDist))
$freqDist[$w]++;
else
$freqDist[$w] = 1;
}
}
You can then sort in descending order and display the distribution of words like this:
arsort($freqDist);
foreach($freqDist as $word => $count)
{
if (strpos($word, '#') !== FALSE)
echo "$word: $count\n";
else
echo "$word: does not contain hashtag, DROPPED\n";
}
You could also use preg_match() to do fancier matching if you want but I've used a naive approach with strpos() to assume that if the word has '#' (anywhere) it's a hashtag.
Other functions of possible use to you:
str_word_count(): Return information about words used in a string.
array_count_values(): Counts all the values of an array.

PHP preg_replace inside for loop

I'm currently trying out this PHP preg_replace function and I've run into a small problem. I want to replace all the tags with a div with an ID, unique for every div, so I thought I would add it into a for loop. But in some strange way, it only do the first line and gives it an ID of 49, which is the last ID they can get. Here's my code:
$res = mysqli_query($mysqli, "SELECT * FROM song WHERE id = 1");
$row = mysqli_fetch_assoc($res);
mysqli_set_charset("utf8");
$lyric = $row['lyric'];
$lyricHTML = nl2br($lyric);
$lines_arr = preg_split('[<br />]',$lyricHTML);
$lines = count($lines_arr);
for($i = 0; $i < $lines; $i++) {
$string = preg_replace(']<br />]', '</h4><h4 id="no'.$i.'">', $lyricHTML, 1);
echo $i;
}
echo '<h4>';
echo $string;
echo '</h4>';
How it works is that I have a large amount of text in my database, and when I add it into the lyric variable, it's just plain text. But when I nl2br it, it gets after every line, which I use here. I get the number of by using the little "lines_arr" method as you can see, and then basically iterate in a for loop.
The only problem is that it only outputs on the first line and gives that an ID of 49. When I move it outside the for loop and removes the limit, it works and all lines gets an <h4> around them, but then I don't get the unique ID I need.
This is some text I pulled out from the database
Mama called about the paper turns out they wrote about me
Now my broken heart´s the only thing that's broke about me
So many people should have seen what we got going on
I only wanna put my heart and my life in songs
Writing about the pain I felt with my daddy gone
About the emptiness I felt when I sat alone
About the happiness I feel when I sing it loud
He should have heard the noise we made with the happy crowd
Did my Gran Daddy know he taught me what a poem was
How you can use a sentence or just a simple pause
What will I say when my kids ask me who my daddy was
I thought about it for a while and I'm at a loss
Knowing that I´m gonna live my whole life without him
I found out a lot of things I never knew about him
All I know is that I´ll never really be alone
Cause we gotta lot of love and a happy home
And my goal is to give every line an <h4 id="no1">TEXT</h4> for example, and the number after no, like no1 or no4 should be incremented every iteration, that's why I chose a for-loop.
Looks like you need to escape your regexp
preg_replace('/\[<br \/\]/', ...);
Really though, this is a classic XY Problem. Instead of asking us how to fix your solution, you should ask us how to solve your problem.
Show us some example text in the database and then show us how you would like it to be formatted. It's very likely there's a better way.
I would use array_walk for this. ideone demo here
$lines = preg_split("/[\r\n]+/", $row['lyric']);
array_walk($lines, function(&$line, $idx) {
$line = sprintf("<h4 id='no%d'>%s</h4>", $idx+1, $line);
});
echo implode("\n", $lines);
Output
<h4 id="no1">Mama called about the paper turns out they wrote about me</h4>
<h4 id="no2">Now my broken heart's the only thing that's broke about me</h4>
<h4 id="no3">So many people should have seen what we got going on</h4>
...
<h4 id="no16">Cause we gotta lot of love and a happy home</h4>
Explanation of solution
nl2br doesn't really help us here. It converts \n to <br /> but then we'd just end up splitting the string on the br. We might as well split using \n to start with. I'm going to use /[\r\n]+/ because it splits one or more \r, \n, and \r\n.
$lines = preg_split("/[\r\n]+/", $row['lyric']);
Now we have an array of strings, each containing one line of lyrics. But we want to wrap each string in an <h4 id="noX">...</h4> where X is the number of the line.
Ordinarily we would use array_map for this, but the array_map callback does not receive an index argument. Instead we will use array_walk which does receive the index.
One more note about this line, is the use of &$line as the callback parameter. This allows us to alter the contents of the $line and have it "saved" in our original $lyrics array. (See the Example #1 in the PHP docs to compare the difference).
array_walk($lines, function(&$line, $idx) {
Here's where the h4 comes in. I use sprintf for formatting HTML strings because I think they are more readable. And it allows you to control how the arguments are output without adding a bunch of view logic in the "template".
Here's the world's tiniest template: '<h4 id="no%d">%s</h4>'. It has two inputs, %d and %s. The first will be output as a number (our line number), and the second will be output as a string (our lyrics).
$line = sprintf('<h4 id="no%d">%s</h4>', $idx+1, $line);
Close the array_walk callback function
});
Now $lines is an array of our newly-formatted lyrics. Let's output the lyrics by separating each line with a \n.
echo implode("\n", $lines);
Done!
If your text in db is in every line why just not explode it with \n character?
Always try to find a solution without using preg set of functions, because they are heavy memory consumers:
I would go lke this:
$lyric = $row['lyric'];
$lyrics =explode("\n",$lyrics);
$lyricsHtml=null;
$i=0;
foreach($lyrics as $val){
$i++;
$lyricsHtml[] = '<h4 id="no'.$i.'">'.$val.'</h4>';
}
$lyricsHtml = implode("\n",$lyricsHtml);
An other way with preg_replace_callback:
$id = 0;
$lyric = preg_replace_callback('~(^)|$~m',
function ($m) use (&$id) {
return (isset($m[1])) ? '<h4 id="no' . ++$id . '">' : '</h4>'; },
$lyric);

First Char of any words in a sentences

I would like to extract any first char of any word inside a sentence like:
Full time become FT
Part time become PT
Contractor become C
Temp become T
Is that possible in smarty PHP and how? I have {$listing.EmployementType}.
{assign var=firstWord value=" "|explode:"$listing.EmployementType"}
then access the first word by $firstWord[0]..
you might want to look in to it further..
http://www.smarty.net/forums/viewtopic.php?p=6581&sid=f8cc8323a968506f305c803e94f522f1
Here is a somewhat functional way to do it:
function firstLetter($word) {
return uc($word[0]);
}
$result = implode('', array_map('firstLetter', explode(' ', $sentence)));
http://au2.php.net/array_map
http://au1.php.net/explode
http://au1.php.net/manual/en/function.implode.php
Edit: alternatively,
$result = '';
$words = explode(' ', $sentence);
foreach ($words as $word) {
$result .= uc($word[0]);
}
Actually shorter and probably more readable, but less fun haha.
Edit 2: sorry, didn't realise smarty was a requirement of the question. I'll just leave this here in case someone else looking for a pure php solution stumbles upon this question.
Create a smarty plugin that fits your requirements. In this case, a modifier plugin.
If you know some basic php it's very easy: http://www.smarty.net/docs/en/plugins

Paste (Excel-) Table into Form, convert to HTML and process Result after Submit

What we’re trying to accomplish is: Copy a simple, two column table (ECTS, grade) from a database application, paste the content into a HTML form, having it converted to HTML and submitted to do some PHP processing (which, fyi, is: in every tr multiply td[1] with td[2], sum all td[1], sum all td[2] – I think I know how to get this done with PHP; then, by using tcpdf, automatically create the certificates, already created that part).
For the conversion part: I tried several Javascript solutions which do work just fine (such as Help interpret/implement "Copy/Paste from Excel to a web page" answer?) – but I can't manage to put the Javascript output into a form field (input/textarea). I tried to stringify the [Object object], to no avail (JS noob here).
The best solution would be Danny Sanchez’ Tableize! (http://tableizer.journalistopia.com/) or the one from pressbin.com (http://pressbin.com/tools/excel_to_html_table/index.html) – they do exactly what we need. Alas, neither of them responds to my enquiry …
Has anyone an idea or adivse for us?
I hope I was able to explain our problem in a comprehensible way – I shall be glad to offer additional information.
("We" = A unit at a University where we, amongst other things, have to calculate grades averages which is a very exhausting task doing it by hand.)
The OP wrote in an edit:
Solution:
if (isset($_POST['ed'])) {
$input = str_replace(",", ".", $_POST['ed']);
$notenarray = explode( "\n", $input);
$gewnote = 0;
$totalnote = 0;
$totalects = 0;
foreach($notenarray as $key => $val) {
$arrayrow[$key] = preg_split("/[\t]/", $val);
$gewnote += array_product($arrayrow[$key]);
$totalects += $arrayrow[$key][0];
$totalnote += $arrayrow[$key][1];
}

Categories