I have a function on my php site that fills rtf templates with customer data.
It replaces placeholders that look like this %%PLACEHOLDER%%.
Now I want to replace a placeholder with a string that has tabs and line breaks in it. I can't figure out how to do this. I did read this post but the anwser doesn't work for me. In the final file it just displays {\pard\par} in plain text.
Replace function:
function populate_RTF($vars, $doc_file)
{
$replacements = array ('\\' => "\\\\",
'{' => "\{",
'}' => "\}");
$document = file_get_contents($doc_file);
if(!$document) {
return false;
}
foreach($vars as $key=>$value) {
$search = "%%".strtoupper($key)."%%";
foreach($replacements as $orig => $replace) {
$value = str_replace($orig, $replace, $value);
}
$document = str_replace($search, $value, $document);
}
return $document;
}
File where I use the function:
function MakeString()
{
foreach(/*for each here*/)
{
$string = $name. "\tab" . $gpu . "\tab" . $cpu . "{\pard\par}";
$string .= $name. "\tab" . $gpu . "\tab" . $cpu . "{\pard\par}";
$string .= $name. "\tab" . $gpu . "\tab" . $cpu . "{\pard\par}";
}
return $string;
}
$vars = array
(
'name' => $info['name'],
'address' => $info['address'],
'phone' => $info['phone'],
'string-here' => MakeString(),
);
$new_rtf = populate_RTF($vars, $template);
$fr = fopen($saveLocation.$filename, 'w') ;
fwrite($fr, $new_rtf);
fclose($fr);
RTF output now is:
John \tabAsus GTX 1060\tabIntel I7{\pard\par}Mike\tabAsus GTX 1080\tabAMD FX 8120{\pard\par}
RTF output should be:
John Asus GTX 1060 Intel I7
Mike Asus GTX 1080 AMD FX 8120
Someone that can help me with this?
Related
I am refactoring some legacy PHP code (version 5.5) and I need to refactor a function to use preg_replace_callback() from preg_replace() (this is because of a \e evaluation deprecation) however what is being passed into the only 2 preg_replace() calls are arrays of search patterns and arrays of replacements.
I am aware I need to pass in a callback function to preg_replace_callback() but what would be the way to go about this when each pattern is different?
function format($in, $options = 0)
{
if (!$options) {
$options = FORMAT_BREAKS | FORMAT_HTMLCHARS | FORMAT_CENSOR;
}
if ($options & FORMAT_CENSOR) {
if (!$this->replaces_loaded) {
$this->get_replaces();
}
if ($this->censor) {
$in = preg_replace($this->censor, '####', $in);
}
}
if ($options & FORMAT_MBCODE) {
$search = array(
'~(^|\s)([a-z0-9-_.]+#[a-z0-9-.]+\.[a-z0-9-_.]+)~i',
'~(^|\s)(http|https|ftp)://(\w+[^\s\[\]]+)~ise'
);
$replace = array(
'\\1[email]\\2[/email]',
'\'\\1[url]\' .wordwrap(\'\\2://\\3\', 1, \' \', 1) . \'[/url]\''
);
$brackets = (strpos($in, '[') !== false) && (strpos($in, ']') !== false);
if ($brackets) {
$b_search = array(
'~\[code](.*?)\[/code]~ise',
'~\[php](.*?)\[/php]~ise',
'~\[php=([0-9]+?)](.*?)\[/php]~ise',
'~\[img](http|https|ftp)://(.*?)\[/img]~ise',
'~\[url](.*?)\[/url]~ise',
'~\[url=(http|https|ftp)://(.+?)](.+?)\[/url]~ise'
);
$b_replace = array(
'\'[code]\' . function (array $matches){ return base64_encode(\'\\1\') . \'[/code]\'',
'\'[php]\' . base64_encode(\'\\1\') . \'[/php]\'',
'\'[php=\\1]\' . base64_encode(\'\\2\') . \'[/php]\'',
'\'[img]\' . wordwrap(\'\\1://\\2\', 1, \' \', 1) . \'[/img]\'',
'\'[url]\' . wordwrap(\'\\1\\2\', 1, \' \', 1) . \'[/url]\'',
'\'[url=\' . wordwrap(\'\\1://\\2\', 1, \' \', 1) . \']\\3[/url]\''
);
$search = array_merge($search, $b_search);
$replace = array_merge($replace, $b_replace);
error_log(print_r($replace));
}
$in = preg_replace($search, $replace, $in);
$brackets = (strpos($in, '[') !== false) && (strpos($in, ']') !== false); //We may have auto-parsed a URL, adding a bracket
}
$strtr = array();
if ($options & FORMAT_HTMLCHARS) {
$strtr['&'] = '&';
$strtr['"'] = '"';
$strtr['\''] = ''';
$strtr['<'] = '<';
$strtr['>'] = '>';
}
if ($options & FORMAT_BREAKS) {
$strtr["\n"] = "<br />\n";
}
if ($this->user['user_view_emoticons'] && ($options & FORMAT_EMOTICONS)) {
if (!$this->replaces_loaded) {
$this->get_replaces();
}
$strtr = array_merge($strtr, $this->emotes['replacement']);
}
$in = strtr($in, $strtr);
if (($options & FORMAT_MBCODE) && $brackets) {
$search = array(
'~\[(/)?([bi])]~i',
'~\[u]~i',
'~\[s]~i',
'~\[/[us]]~i',
'~\[url](h t t p|h t t p s|f t p) : / /(.+?)\[/url]~ise',
'~\[url=(h t t p|h t t p s|f t p) : / /(.+?)](.+?)\[/url]~ise',
'~\[email]([a-z0-9-_.]+#[a-z0-9-.]+\.[a-z0-9-_.]+)?\[/email]~i',
'~\[email=([^<]+?)](.*?)\[/email]~i',
'~\[img](h t t p|h t t p s|f t p) : / /(.*?)\[/img]~ise',
'~\[(right|center)](.*?)\[/\1]~is',
'~\[code](.*?)\[/code]~ise',
'~\[php](.*?)\[/php]~ise',
'~\[php=([0-9]+?)](.*?)\[/php]~ise',
'~\[color=(\S+?)](.*?)\[/color]~is',
'~\[font=(.+?)](.*?)\[/font]~is',
'~\[size=([0-9]+?)](.*?)\[/size]~is'
);
$replace = array(
'<\\1\\2>',
'<span style=\'text-decoration:underline\'>',
'<span style=\'text-decoration:line-through\'>',
'</span>',
'\'\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'\'',
'\'\\3\'',
'\\1',
'\\2',
'\'<img src="\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'" alt="\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'" />\'',
'<div align="\\1">\\2</div>',
'$this->format_code(\'\\1\', 0)',
'$this->format_code(\'\\1\', 1)',
'$this->format_code(\'\\2\', 1, \'\\1\')',
'<span style=\'color:\\1\'>\\2</span>',
'<span style=\'font-family:\\1\'>\\2</span>',
'<span style=\'font-size:\\1ex\'>\\2</span>'
);
if ((substr_count($in, '[quote]') + substr_count($in, '[quote=')) == substr_count($in, '[/quote]')) {
$search[] = '~\[quote=(.+?)]~i';
$search[] = '~\[quote]~i';
$search[] = '~\[/quote]~i';
$replace[] = '<table style="width:90%; margin-left:5%; margin-right:5%;" border="0" cellpadding="3" cellspacing="0"><tr><td><b>\\1 ' . $this->lang->main_said . ':</b></td></tr><tr><td class="quote">';
$replace[] = '<table style="width:90%; margin-left:5%; margin-right:5%;" border="0" cellpadding="3" cellspacing="0"><tr><td><b>' . $this->lang->main_quote . ':</b></td></tr><tr><td class="quote">';
$replace[] = '</td></tr></table>';
}
$in = preg_replace_callback($search, $replace, $in);
$in = str_replace(array(' ', "\t", '&#'), array(' ', ' ', '&#'), $in);
}
return $in;
}
I tested trying to place an anonymous functions directly into the replacement arrays but was served the error: Object of class Closure could not be converted to string. But perhaps I may have gone about it incorrectly?
$replace = array(
'\\1[email]\\2[/email]',
"'\'\\1[url]\'" . function (array $matches) {return wordwrap($matches[1], $matches[2], $matches[3], $matches[4]); } . " \'[/url]\''"
);
Advice would be much appreciated.
Create an associative array where the keys contain regex patterns and the values contain the callbacks (no prepending/appending strings to the callbacks).
I am not going to rewrite that behemoth from my phone, so I'll demonstrate a single replacement.
Feed your array of patterns and callbacks to preg_replace_callback_array().
Code: (Demo)
$patternCallbacks = [
'~\[code](.*?)\[/code]~is' =>
function($m) {
return '[code]' . base64_encode($m[1]) . '[/code]';
},
// add more elements as needed...
];
echo preg_replace_callback_array(
$patternCallbacks,
'This is my [code]script[/code] to display'
);
Output:
This is my [code]c2NyaXB0[/code] to display
Edit, since you cannot use preg_replace_callback_array(), you will need to make iterated calls of preg_replace_callback().
Code: (Demo)
$patternCallbacks = [
'~\[code](.*?)\[/code]~is' =>
function($m) {
return '[code]' . base64_encode($m[1]) . '[/code]';
},
'~\[php(?:=\d+)?]\K(.*?)\[/php]~is' =>
function($m) {
return base64_encode($m[1]) . '[/php]';
},
];
$text = <<<TEXT
This is my [code]script[/code] to display.
It has [php]unnumbered tag
code[/php] and [php=8]numbered tag code[/php].'
TEXT;
foreach ($patternCallbacks as $pattern => $callback) {
$text = preg_replace_callback($pattern, $callback, $text);
}
echo $text;
Output:
This is my [code]c2NyaXB0[/code] to display.
It has [php]dW5udW1iZXJlZCB0YWcKIGNvZGU=[/php] and [php=8]bnVtYmVyZWQgdGFnIGNvZGU=[/php].
I need to update a file using php
Sample file:
#Start#
No. of records: 2
Name: My name,
Age: 18,
Date: 2013-07-11||
Name: 2nd name,
Age: 28,
Date: 2013-07-11||
#End#
I need to edit 'No. of records' on each time I add another record on file. And another record needs to be before '#End#'
I'm using
$Handle = fopen($File, 'a');
$data = .......
fwrite($Handle, $Data);
to add records
How can I edit 'No. of records' & add data before '#End#'?
Instead of modifying the file I would parse it, change the data in PHP an rewrite the file after that.
To achieve this, I would firstly create a function that parses the input into php arrays:
function parse($file) {
$records = array();
foreach(file($file) as $line) {
if(preg_match('~^Name: (.*),~', $line, $matches)) {
$record = array('name' => $matches[1]);
}
if(preg_match('~^Age: (.*),~', $line, $matches)) {
$record ['age'] = $matches[1];
}
if(preg_match('~^Date: (.*)\|\|~', $line, $matches)) {
$record ['date'] = $matches[1];
$records [] = $record;
}
}
return $records;
}
Secondly I would create a function that flattens the arrays back into the same file format again:
function flatten($records, $file) {
$str = '#Start#';
$str .= "\n\n";
$str .= 'No. of records: ' . count($records) . "\n\n";
foreach($records as $record) {
$str .= 'Name: ' . $record['name'] . ",\n";
$str .= 'Age: ' . $record['name'] . ",\n";
$str .= 'Date: ' . $record['name'] . "||\n\n";
}
file_put_contents($file, $str . '#End#');
}
Then use it like this:
$records = parse('your.file');
var_dump($records);
$records []= array(
'name' => 'hek2mgl',
'age' => '36',
'date' => '07/11/2013'
);
flatten($records, 'your.file');
In case if file is relatively small (easily fits in memory), you can use file() function. It will return array, which you can iterate, etc.
If the file is larger, you'll need to read it in the loop using fgets(), writing data to the new temporary file and replacing original file with it after you're done
Upon searching I found PHP function that do inserts before all newlines in a string which is
nl2br();
example:
<?php
echo nl2br("This is an example\r\n where line breaks\r\n added", false);
?>
Above code Output :
This is an example<br\>
where line breaks<br\>
added
What I wanted to have output instead of <br/> I will wrap the string with the tags before and after all newlines
example output from code above wrap string with span
<span>This is an example</span>
<span>where line breaks</span>
<span>added</span>
Is there PHP function exist to this? or a custom PHP function
$str = "This is an example\r\n where line breaks\r\n added";
$str = explode("\r\n",$str);
foreach($str as $key => $value) {
echo "<span>".$value."</span>";
}
You could do an "explode" on "\r\n" and loop over each value with a concatenated span.
Something like
$values = explode("\r\n", "one\r\ntwo\r\nthree\r\nfour")
$newvalues = ""
foreach($values as $value){
$newvalues = $newvalues . "<span>" . $value . "</span>"
}
Use file(). It will return the entire file as an array, each being a new line. Iterate through there and add your span's. Not the best way, but if you have a lot of files to do this for, it's just as easy as any other solution. Otherwise, just explode on your delimiter.
function splitToSpans($string) {
$lines = explode('\r\n', $string);
$finalString = '';
foreach ($lines as $line) {
$finalString .= '<span>' . $line . '</span>';
}
return $finalString;
}
Something like:
$strout = '';
$lines = explode(PHP_EOL, $input);
foreach ($lines as $line) {
$strout .= "<span>$line</span>";
}
Option 1:
<?php
$string = "Line 1
Line 2
Line 3";
$string = preg_replace('/^(.*)$/m', '<span>$1</span>', $string);
echo $string;
Option 2:
<?php
$string = "Line 1\r\nLine 2\r\nLine 3";
$string = array_map(function($value) {
return "<span>$value</span>";
}, explode("\r\n", $string));
echo implode("\r\n", $string);
This function splits the string based on either a CRLF or LF only and then wraps it into a <span> tag, applying proper escaping (important):
function nl2span($str)
{
$r = '';
foreach (preg_split("/\r?\n/", $str) as $line) {
$r .= '<span>' . htmlspecialchars($line). '</span>';
}
return $r;
}
If your line endings are always CRLF you can replace the preg_split() with a more conventional explode("\r\n", ...).
$string = "This is an example\r\n where line breaks\r\n added";
var_dump($string);
// string(46) "This is an example
// where line breaks
// added"
array_map(function($s){echo sprintf('<span>%s</span>', trim($s));}, explode("\r\n", $string));
// <span>This is an example</span>
// <span>where line breaks</span>
// <span>added</span>
This is useful:
function nl2span( $str) {
return '<span>' . implode( '</span><span>', explode( "\r\n", $str ) ) . '</span>';
}
Read through the answers, and noone had mentioned this solution...
$string = "This is an example\r\n where line breaks\r\n added";
echo '<span>' . str_replace('\r\n', '</span><span>', $string) . '</span>';
I am creating a findSpellings function that has two parameters $word and $allWords. $allwords is an array that has mis-spellings of words that could sound similar to the $word variable. What I am trying to accomplish is to print out all words that are similar to the $word based on the soundex function. I am having trouble printing out the array with words. My function that I have is below. Any help would be greatly appreciated:
<?php
$word = 'stupid';
$allwords = array(
'stupid',
'stu and pid',
'hello',
'foobar',
'stpid',
'supid',
'stuuupid',
'sstuuupiiid',
);
function findSpellings($word, $allWords){
while(list($id, $str) = each($allwords)){
$soundex_code = soundex($str);
if (soundex($word) == $soundex_code){
//print '"' . $word . '" sounds like ' . $str;
return $word;
return $allwords;
}
else {
return false;
}
}
}
print_r(findSpellings($word, $allWords));
?>
if (soundex($word) == $soundex_code){
//print '"' . $word . '" sounds like ' . $str;
return $word;
return $allwords;
}
You can't have 2 returns, the first return will exit the code.
You could just do something like this:
if (soundex($word) == $soundex_code){
//print '"' . $word . '" sounds like ' . $str;
$array = array('word' => $word, 'allWords' => $allWords);
return $array;
}
And then just retrieve the values out of $array like so:
$filledArray = findSpellings($word, $allWords);
echo "You typed".$filledArray['word'][0]."<br/>";
echo "Were you looking for one of the following words?<br/>";
foreach($filledArray['allWords'] as $value)
{
echo $value;
}
I'm creating an upload form that has a text area for users to input cooking recipes with. Essentially, what I want to do is wrap each line in a <li> tag for output purposes. I've been trying to manipulate the nl2br function but to no avail. Can anyone help?
I'm retrieving the text area's content via POST and storing entries in a MySQL database.
Here's what the code looks like at the moment (the check_input function strips slashes, etc.):
$prepText=check_input($_POST['preparationText']);
$cookText=check_input($_POST['cookingText']);
Explode the string by \n then wrap each line in an li tag.
<?php
$string = "line 1\nline 2\nline3";
$bits = explode("\n", $string);
$newstring = "<ol>";
foreach($bits as $bit)
{
$newstring .= "<li>" . $bit . "</li>";
}
$newstring .= "</ol>";
Not quite pretty, but an idea that comes to mind is to :
explode the string, using newline as a separator
and implode the array, using </li><li> between items :
Which could be translated to something like this :
$new_string = '<li>' . implode('</li><li>', explode("\n", $old_string)) . '</li>';
(Yeah, bad idea -- don't do that, especially if the text is long)
Another solution, way cleaner, would be to just replace the newlines in your string by </li><li> :
(wrapping the resulting string inside <li> and </li>, to open/close those)
$new_string = '<li>' . str_replace("\n", '</li><li>', $old_string) . '</li>';
With that idea, for example, the following portion of code :
$old_string = <<<STR
this is
an example
of a
string
STR;
$new_string = '<li>' . str_replace("\n", '</li><li>', $old_string) . '</li>';
var_dump($new_string);
Would get you this kind of output :
string '<li>this is</li><li>an example</li><li>of a </li><li>string</li>' (length=64)
I created a function based on Richard's answer in case it saves anyone some time!
/**
* #param string $str - String containing line breaks
* #param string $tag - ul or ol
* #param string $class - classes to add if required
*/
function nl2list($str, $tag = 'ul', $class = '')
{
$bits = explode("\n", $str);
$class_string = $class ? ' class="' . $class . '"' : false;
$newstring = '<' . $tag . $class_string . '>';
foreach ($bits as $bit) {
$newstring .= "<li>" . $bit . "</li>";
}
return $newstring . '</' . $tag . '>';
}
function nl2li($str)
{
if (!isset($str)) return false;
$arr = explode("\r\n", $str);
$li = array_map(function($s){ return '<li>'.$s.'</li>'; }, $arr);
return '<ul>'.implode($li).'</ul>';
}
Input:
Line 1\r\nLine2\r\nLine3\r\n
Output:
<ul><li>Line 1</li><li>Line 2</li><li>Line 3</li></ul>
The simplest way to do it:
function ln2ul($string) {
return '<ul><li>' . str_replace("\n", '</li><li>', trim($string)) . '</li></ul>';
}